aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPeter Andersson <[email protected]>2010-02-17 15:59:05 +0000
committerErlang/OTP <[email protected]>2010-02-17 15:59:05 +0000
commit332591f03f7bc4585c8c108c192ab3bba6fec12c (patch)
treec3d06e8750d53d0f157d61cd4c5f991959a05a51 /lib
parentf29538e8002cf0e37fa4f988fbf5484c46513bf4 (diff)
downloadotp-332591f03f7bc4585c8c108c192ab3bba6fec12c.tar.gz
otp-332591f03f7bc4585c8c108c192ab3bba6fec12c.tar.bz2
otp-332591f03f7bc4585c8c108c192ab3bba6fec12c.zip
OTP-8311: Various updates and fixes in Common Test and Test Server
Diffstat (limited to 'lib')
-rw-r--r--lib/common_test/src/ct_framework.erl36
-rw-r--r--lib/common_test/src/ct_run.erl12
-rw-r--r--lib/common_test/src/ct_telnet.erl59
-rw-r--r--lib/common_test/src/ct_telnet_client.erl179
-rw-r--r--lib/common_test/src/ct_testspec.erl76
-rw-r--r--lib/common_test/src/ct_util.hrl13
-rw-r--r--lib/common_test/src/unix_telnet.erl39
-rw-r--r--lib/common_test/test/Makefile94
-rw-r--r--lib/common_test/test/common_test.spec1
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl558
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_1_SUITE.erl116
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_2_SUITE.erl117
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_3_SUITE.erl116
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_4_SUITE.erl115
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_5_SUITE.erl115
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_6_SUITE.erl116
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_7_SUITE.erl116
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_8_SUITE.erl152
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl185
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/lib_error_1_SUITE.erl188
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/lib_lines.erl25
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/lib_no_lines.erl23
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/no_compile_SUITE.erl115
-rw-r--r--lib/common_test/test/ct_event_handler_SUITE.erl170
-rw-r--r--lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl127
-rw-r--r--lib/common_test/test/ct_event_handler_SUITE_data/event_handling_1/test/eh_11_SUITE.erl141
-rw-r--r--lib/common_test/test/ct_groups_test_1_SUITE.erl1226
-rw-r--r--lib/common_test/test/ct_groups_test_1_SUITE_data/groups_1/test/groups_11_SUITE.erl280
-rw-r--r--lib/common_test/test/ct_groups_test_1_SUITE_data/groups_1/test/groups_12_SUITE.erl310
-rw-r--r--lib/common_test/test/ct_groups_test_1_SUITE_data/groups_2/test/groups_21_SUITE.erl280
-rw-r--r--lib/common_test/test/ct_groups_test_1_SUITE_data/groups_2/test/groups_22_SUITE.erl310
-rw-r--r--lib/common_test/test/ct_groups_test_2_SUITE.erl110
-rw-r--r--lib/common_test/test/ct_groups_test_2_SUITE_data/groups_1/missing_conf_SUITE.erl62
-rw-r--r--lib/common_test/test/ct_skip_SUITE.erl565
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_10_SUITE.erl130
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_11_SUITE.erl136
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_1_SUITE.erl130
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_2_SUITE.erl127
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_3_SUITE.erl132
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_4_SUITE.erl126
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_5_SUITE.erl123
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_6_SUITE.erl136
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_7_SUITE.erl130
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_8_SUITE.erl130
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_9_SUITE.erl166
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_1_SUITE.erl131
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_2_SUITE.erl135
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_3_SUITE.erl132
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_4_SUITE.erl152
-rw-r--r--lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_5_SUITE.erl131
-rw-r--r--lib/common_test/test/ct_smoke_test_SUITE.erl569
-rw-r--r--lib/common_test/test/ct_smoke_test_SUITE_data/happy_1/cfg/config1.cfg5
-rw-r--r--lib/common_test/test/ct_smoke_test_SUITE_data/happy_1/test/happy_11_SUITE.erl196
-rw-r--r--lib/common_test/test/ct_smoke_test_SUITE_data/happy_2_cfg/config1.cfg5
-rw-r--r--lib/common_test/test/ct_smoke_test_SUITE_data/happy_2_test/happy_21_SUITE.erl196
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE.erl253
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/skipped_by_spec_1_SUITE.erl127
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/skipped_by_spec_2_SUITE.erl127
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl191
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_2_SUITE.erl127
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_3_SUITE.erl128
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_4_SUITE.erl127
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_5_SUITE.erl128
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_6_SUITE.erl111
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_7_SUITE.erl93
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_8_SUITE.erl52
-rw-r--r--lib/common_test/test/ct_test_support.erl976
-rw-r--r--lib/common_test/test/ct_test_support_eh.erl127
-rw-r--r--lib/common_test/vsn.mk2
-rw-r--r--lib/test_server/src/test_server.erl30
-rw-r--r--lib/test_server/src/test_server_ctrl.erl10
-rw-r--r--lib/test_server/src/test_server_line.erl17
-rw-r--r--lib/test_server/src/test_server_sup.erl23
-rw-r--r--lib/test_server/test/Makefile95
-rw-r--r--lib/test_server/test/test_server.cover20
-rw-r--r--lib/test_server/test/test_server.spec2
-rw-r--r--lib/test_server/test/test_server_SUITE.erl554
-rw-r--r--lib/test_server/test/test_server_SUITE_data/dummy_file1
-rw-r--r--lib/test_server/test/test_server_conf01_SUITE.erl187
-rw-r--r--lib/test_server/test/test_server_conf02_SUITE.erl294
-rw-r--r--lib/test_server/test/test_server_line_SUITE.erl122
-rw-r--r--lib/test_server/test/test_server_line_SUITE_data/Makefile.src6
-rw-r--r--lib/test_server/test/test_server_line_SUITE_data/parse_transform_test.erl59
-rw-r--r--lib/test_server/test/test_server_parallel01_SUITE.erl518
-rw-r--r--lib/test_server/test/test_server_shuffle01_SUITE.erl471
-rw-r--r--lib/test_server/test/test_server_skip_SUITE.erl43
-rw-r--r--lib/test_server/vsn.mk2
87 files changed, 14112 insertions, 176 deletions
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 8456251b29..ed8b564921 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% 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%
%%
@@ -27,7 +27,7 @@
-export([init_tc/3, end_tc/3, get_suite/2, report/2, warn/1]).
-export([error_notification/4]).
--export([error_in_suite/1]).
+-export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]).
-include("ct_event.hrl").
-include("ct_util.hrl").
@@ -751,8 +751,15 @@ find_group(Mod, Name, Defs) ->
end.
make_conf(Mod, Name, Props, TestSpec) ->
- {conf,[{name,Name}|Props],
- {Mod,init_per_group},TestSpec,{Mod,end_per_group}}.
+ {InitConf,EndConf} =
+ case erlang:function_exported(Mod,init_per_group,2) of
+ true ->
+ {{Mod,init_per_group},{Mod,end_per_group}};
+ false ->
+ {{?MODULE,ct_init_per_group},
+ {?MODULE,ct_end_per_group}}
+ end,
+ {conf,[{name,Name}|Props],InitConf,TestSpec,EndConf}.
get_all(Mod, ConfTests) ->
@@ -916,6 +923,19 @@ check_multiple(Mod,Seq,TCs) ->
error_in_suite(Config) ->
Reason = test_server:lookup_config(error,Config),
exit(Reason).
+
+%% if the group config functions are missing in the suite,
+%% use these instead
+ct_init_per_group(GroupName, Config) ->
+ ct_logs:log("WARNING", "init_per_group/2 for ~w missing in suite, using default.",
+ [GroupName]),
+ Config.
+
+ct_end_per_group(GroupName, _) ->
+ ct_logs:log("WARNING", "end_per_group/2 for ~w missing in suite, using default.",
+ [GroupName]),
+ ok.
+
%%%-----------------------------------------------------------------
%%% @spec report(What,Data) -> ok
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index a1e2358578..6b1063f74c 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% 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%
%%
@@ -1515,7 +1515,7 @@ run_make(Targets, TestDir0, Mod, UserInclude) ->
debug_info],
Result =
if Mod == all ; Targets == helpmods ->
- case (catch ct_make:all([noexec])) of
+ case (catch ct_make:all([noexec|ErlFlags])) of
{'EXIT',_} = Failure ->
Failure;
MakeInfo ->
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index c19d312f01..c6f5fd7df4 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2003-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%
%%
@@ -21,27 +21,28 @@
%%%
%%% <p>Use this module to set up telnet connections, send commands and
%%% perform string matching on the result.
-%%% (See the <code>unix_telnet</code> manual page for information
-%%% about how ct_telnet may be used specifically with unix hosts.)</p>
+%%% See the <c>unix_telnet</c> manual page for information about how to use
+%%% ct_telnet, and configure connections, specifically for unix hosts.</p>
%%% <p>The following default values are defined in ct_telnet:</p>
%%% <pre>
%%% Connection timeout = 10 sec (time to wait for connection)
%%% Command timeout = 10 sec (time to wait for a command to return)
%%% Max no of reconnection attempts = 3
%%% Reconnection interval = 5 sek (time to wait in between reconnection attempts)
-%%% </pre>
+%%% Keep alive = true (will send NOP to the server every 10 sec if connection is idle)</pre>
%%% <p>These parameters can be altered by the user with the following
%%% configuration term:</p>
%%% <pre>
%%% {telnet_settings, [{connect_timeout,Millisec},
%%% {command_timeout,Millisec},
%%% {reconnection_attempts,N},
-%%% {reconnection_interval,Millisec}]}.
-%%% </pre>
+%%% {reconnection_interval,Millisec},
+%%% {keep_alive,Bool}]}.</pre>
%%% <p><code>Millisec = integer(), N = integer()</code></p>
%%% <p>Enter the <code>telnet_settings</code> term in a configuration
%%% file included in the test and ct_telnet will retrieve the information
-%%% automatically.</p>
+%%% automatically. Note that <c>keep_alive</c> may be specified per connection if
+%%% required. See <c>unix_telnet</c> for details.</p></doc>
%%% @type connection_type() = telnet | ts1 | ts2
@@ -88,7 +89,9 @@
buffer=[],
prompt=false,
name,
- target_mod,extra,
+ target_mod,
+ keep_alive,
+ extra,
conn_to=?DEFAULT_TIMEOUT,
com_to=?DEFAULT_TIMEOUT,
reconns=?RECONNS,
@@ -150,7 +153,7 @@ open(KeyOrName,ConnType,TargetMod) ->
%%% name can only be closed with the handle value.</p>
%%%
%%% <p><code>TargetMod</code> is a module which exports the functions
-%%% <code>connect(Ip,Port,Extra)</code> and <code>get_prompt_regexp()</code>
+%%% <code>connect(Ip,Port,KeepAlive,Extra)</code> and <code>get_prompt_regexp()</code>
%%% for the given <code>TargetType</code> (e.g. <code>unix_telnet</code>).</p>
open(KeyOrName,ConnType,TargetMod,Extra) ->
case ct:get_config({KeyOrName,ConnType}) of
@@ -169,9 +172,18 @@ open(KeyOrName,ConnType,TargetMod,Extra) ->
P -> {IP,P}
end
end,
+ KeepAlive =
+ case ct:get_config({KeyOrName,keep_alive}) of
+ undefined ->
+ case ct:get_config({telnet_settings,keep_alive}) of
+ undefined -> true;
+ Bool -> Bool
+ end;
+ Bool -> Bool
+ end,
log(heading(open,{KeyOrName,ConnType}),"Opening connection to: ~p",[Addr1]),
ct_gen_conn:start(KeyOrName,full_addr(Addr1,ConnType),
- {TargetMod,Extra},?MODULE)
+ {TargetMod,KeepAlive,Extra},?MODULE)
end.
%%%-----------------------------------------------------------------
@@ -373,14 +385,14 @@ expect(Connection,Patterns,Opts) ->
%%%=================================================================
%%% Callback functions
%% @hidden
-init(Name,{Ip,Port,Type},{TargetMod,Extra}) ->
+init(Name,{Ip,Port,Type},{TargetMod,KeepAlive,Extra}) ->
S0 = case ct:get_config(telnet_settings) of
undefined ->
#state{};
Settings ->
set_telnet_defaults(Settings,#state{})
end,
- case catch TargetMod:connect(Ip,Port,S0#state.conn_to,Extra) of
+ case catch TargetMod:connect(Ip,Port,S0#state.conn_to,KeepAlive,Extra) of
{ok,TelnPid} ->
log(heading(init,{Name,Type}),
"Opened telnet connection\n"
@@ -389,13 +401,15 @@ init(Name,{Ip,Port,Type},{TargetMod,Extra}) ->
"Command timeout: ~p\n"
"Reconnection attempts: ~p\n"
"Reconnection interval: ~p\n"
- "Connection timeout: ~p",
+ "Connection timeout: ~p\n"
+ "Keep alive: ~w",
[Ip,Port,S0#state.com_to,S0#state.reconns,
- S0#state.reconn_int,S0#state.conn_to]),
+ S0#state.reconn_int,S0#state.conn_to,KeepAlive]),
{ok,TelnPid,S0#state{teln_pid=TelnPid,
type=type(Type),
name={Name,Type},
target_mod=TargetMod,
+ keep_alive=KeepAlive,
extra=Extra,
prx=TargetMod:get_prompt_regexp()}};
{'EXIT',Reason} ->
@@ -415,6 +429,12 @@ set_telnet_defaults([{reconnection_attempts,Rs}|Ss],S) ->
set_telnet_defaults(Ss,S#state{reconns=Rs});
set_telnet_defaults([{reconnection_interval,RInt}|Ss],S) ->
set_telnet_defaults(Ss,S#state{reconn_int=RInt});
+set_telnet_defaults([{keep_alive,_}|Ss],S) ->
+ set_telnet_defaults(Ss,S);
+set_telnet_defaults([Unknown|Ss],S) ->
+ log(heading(set_telnet_defaults,{telnet_settings,Unknown}),
+ "Bad element in telnet_settings: ~p",[Unknown]),
+ set_telnet_defaults(Ss,S);
set_telnet_defaults([],S) ->
S.
@@ -527,10 +547,11 @@ handle_msg({expect,Pattern,Opts},State) ->
reconnect({Ip,Port,_Type},State) ->
reconnect(Ip,Port,State#state.reconns,State).
reconnect(Ip,Port,N,State=#state{target_mod=TargetMod,
+ keep_alive=KeepAlive,
extra=Extra,
conn_to=ConnTo,
reconn_int=ReconnInt}) ->
- case TargetMod:connect(Ip,Port,ConnTo,Extra) of
+ case TargetMod:connect(Ip,Port,ConnTo,KeepAlive,Extra) of
{ok, NewPid} ->
{ok, NewPid, State#state{teln_pid=NewPid}};
Error when N==0 ->
diff --git a/lib/common_test/src/ct_telnet_client.erl b/lib/common_test/src/ct_telnet_client.erl
index e460a50eac..1a12c5e343 100644
--- a/lib/common_test/src/ct_telnet_client.erl
+++ b/lib/common_test/src/ct_telnet_client.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2003-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%
%%
@@ -32,13 +32,14 @@
-module(ct_telnet_client).
--export([open/1, open/2, open/3, close/1]).
+-export([open/1, open/2, open/3, open/4, close/1]).
-export([send_data/2, get_data/1]).
-define(DBG, false).
-define(TELNET_PORT, 23).
-define(OPEN_TIMEOUT,10000).
+-define(IDLE_TIMEOUT,10000).
%% telnet control characters
-define(SE, 240).
@@ -65,17 +66,20 @@
-define(TERMINAL_TYPE, 24).
-define(WINDOW_SIZE, 31).
--record(state,{get_data}).
+-record(state,{get_data, keep_alive=true}).
open(Server) ->
- open(Server, ?TELNET_PORT, ?OPEN_TIMEOUT).
+ open(Server, ?TELNET_PORT, ?OPEN_TIMEOUT, true).
open(Server, Port) ->
- open(Server, Port, ?OPEN_TIMEOUT).
+ open(Server, Port, ?OPEN_TIMEOUT, true).
open(Server, Port, Timeout) ->
+ open(Server, Port, Timeout, true).
+
+open(Server, Port, Timeout, KeepAlive) ->
Self = self(),
- Pid = spawn(fun() -> init(Self, Server, Port, Timeout) end),
+ Pid = spawn(fun() -> init(Self, Server, Port, Timeout, KeepAlive) end),
receive
{open,Pid} ->
{ok,Pid};
@@ -100,20 +104,18 @@ get_data(Pid) ->
%%%-----------------------------------------------------------------
%%% Internal functions
-init(Parent, Server, Port, Timeout) ->
+init(Parent, Server, Port, Timeout, KeepAlive) ->
case gen_tcp:connect(Server, Port, [list,{packet,0}], Timeout) of
{ok,Sock} ->
- dbg("Connected to: ~p\n", [Server]),
+ dbg("Connected to: ~p (port: ~w, keep_alive: ~w)\n", [Server,Port,KeepAlive]),
send([?IAC,?DO,?SUPPRESS_GO_AHEAD], Sock),
Parent ! {open,self()},
- loop(#state{get_data=10}, Sock, []),
+ loop(#state{get_data=10, keep_alive=KeepAlive}, Sock, []),
gen_tcp:close(Sock);
Error ->
Parent ! {Error,self()}
end.
-
-
loop(State, Sock, Acc) ->
receive
{tcp_closed,_} ->
@@ -137,21 +139,27 @@ loop(State, Sock, Acc) ->
[] ->
dbg("get_data nodata\n",[]),
erlang:send_after(100,self(),{get_data_delayed,Pid}),
- State#state{get_data=State#state.get_data - 1};
+ if State#state.keep_alive == true ->
+ State#state{get_data=State#state.get_data - 1};
+ State#state.keep_alive == false ->
+ State
+ end;
_ ->
Pid ! {data,lists:reverse(lists:append(Acc))},
State
end,
loop(NewState, Sock, []);
{get_data_delayed,Pid} ->
- NewState = case State#state.get_data of
- 0 ->
- send([?IAC,?DO,?NOP], Sock),
- dbg("delayed after 1000\n",[]),
- State#state{get_data=10};
- _ ->
- State
- end,
+ NewState =
+ case State of
+ #state{keep_alive = true, get_data = 0} ->
+ if Acc == [] -> send([?IAC,?NOP], Sock);
+ true -> ok
+ end,
+ State#state{get_data=10};
+ _ ->
+ State
+ end,
NewAcc =
case erlang:is_process_alive(Pid) of
true ->
@@ -160,29 +168,38 @@ loop(State, Sock, Acc) ->
false ->
Acc
end,
- loop(NewState, Sock, NewAcc);
-
+ loop(NewState, Sock, NewAcc);
close ->
dbg("Closing connection\n", []),
gen_tcp:close(Sock),
ok
- after 1000 ->
- case Acc of
- [] -> % no data buffered
- send([?IAC,?DO,?NOP], Sock),
- dbg("after 1000\n",[]);
- _ ->
- true
+ after wait(State#state.keep_alive,?IDLE_TIMEOUT) ->
+ if
+ Acc == [] -> send([?IAC,?NOP], Sock);
+ true -> ok
end,
loop(State, Sock, Acc)
end.
+wait(true, Time) -> Time;
+wait(false, _) -> infinity.
+
send(Data, Sock) ->
- dbg("Sending: ~p\n", [Data]),
+ case Data of
+ [?IAC|_] = Cmd ->
+ cmd_dbg(Cmd);
+ _ ->
+ dbg("Sending: ~p\n", [Data])
+ end,
gen_tcp:send(Sock, Data),
ok.
-check_msg(Sock,[?IAC | Cs], Acc) ->
+%% [IAC,IAC] = buffer data value 255
+check_msg(Sock, [?IAC,?IAC | T], Acc) ->
+ check_msg(Sock, T, [?IAC|Acc]);
+
+%% respond to a command
+check_msg(Sock, [?IAC | Cs], Acc) ->
case get_cmd(Cs) of
{Cmd,Cs1} ->
dbg("Got ", []),
@@ -192,11 +209,15 @@ check_msg(Sock,[?IAC | Cs], Acc) ->
error ->
Acc
end;
-check_msg(Sock,[H|T],Acc) ->
- check_msg(Sock,T,[H|Acc]);
-check_msg(_Sock,[],Acc) ->
+
+%% buffer a data value
+check_msg(Sock, [H|T], Acc) ->
+ check_msg(Sock, T, [H|Acc]);
+
+check_msg(_Sock, [], Acc) ->
Acc.
+
%% Positive responses (WILL and DO).
respond_cmd([?WILL,?ECHO], Sock) ->
@@ -234,6 +255,11 @@ respond_cmd([?DO | Opt], Sock) ->
cmd_dbg(R),
gen_tcp:send(Sock, R);
+%% Commands without options (which we ignore)
+
+respond_cmd(?NOP, _Sock) ->
+ ok;
+
%% Unexpected messages.
respond_cmd([Cmd | Opt], _Sock) when Cmd >= 240, Cmd =< 255 ->
@@ -246,7 +272,10 @@ respond_cmd([Cmd | Opt], _Sock) ->
get_cmd([Cmd | Rest]) when Cmd == ?SB ->
get_subcmd(Rest, []);
-get_cmd([Cmd,Opt | Rest]) ->
+get_cmd([Cmd | Rest]) when Cmd >= 240, Cmd =< 249 ->
+ {?NOP, Rest};
+
+get_cmd([Cmd,Opt | Rest]) when Cmd >= 251, Cmd =< 254 ->
{[Cmd,Opt], Rest};
get_cmd(_Other) ->
@@ -259,46 +288,34 @@ get_subcmd([Opt | Rest], Acc) ->
get_subcmd(Rest, [Opt | Acc]).
-dbg(_Str,_Args) -> ok.
-% if ?DBG -> io:format(_Str,_Args);
-% true -> ok
-% end.
-
-cmd_dbg(_Cmd) -> ok.
-% if ?DBG ->
-% case _Cmd of
-% [?IAC|Cmd1] ->
-% cmd_dbg(Cmd1);
-% [Ctrl|Opts] ->
-% CtrlStr =
-% case Ctrl of
-% ?DO -> "DO";
-% ?DONT -> "DONT";
-% ?WILL -> "WILL";
-% ?WONT -> "WONT";
-% _ -> "CMD"
-% end,
-% Opts1 =
-% case Opts of
-% [Opt] -> Opt;
-% _ -> Opts
-% end,
-% io:format("~s(~w): ~w\n", [CtrlStr,Ctrl,Opts1]);
-% Any ->
-% io:format("Unexpected in cmd_dbg:~n~w~n",[Any])
-% end;
-% true -> ok
-% end.
-
-
-
-
-
-
-
-
-
-
-
-
+dbg(_Str,_Args) ->
+ if ?DBG -> io:format(_Str,_Args);
+ true -> ok
+ end.
+cmd_dbg(_Cmd) ->
+ if ?DBG ->
+ case _Cmd of
+ [?IAC|Cmd1] ->
+ cmd_dbg(Cmd1);
+ [Ctrl|Opts] ->
+ CtrlStr =
+ case Ctrl of
+ ?DO -> "DO";
+ ?DONT -> "DONT";
+ ?WILL -> "WILL";
+ ?WONT -> "WONT";
+ ?NOP -> "NOP";
+ _ -> "CMD"
+ end,
+ Opts1 =
+ case Opts of
+ [Opt] -> Opt;
+ _ -> Opts
+ end,
+ io:format("~s(~w): ~w\n", [CtrlStr,Ctrl,Opts1]);
+ Any ->
+ io:format("Unexpected in cmd_dbg:~n~w~n",[Any])
+ end;
+ true -> ok
+ end.
diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl
index 21a2f82a54..4378ec5a52 100644
--- a/lib/common_test/src/ct_testspec.erl
+++ b/lib/common_test/src/ct_testspec.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2006-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%
%%
@@ -231,9 +231,11 @@ collect_tests_from_file(Specs,Nodes,Relaxed) when is_list(Nodes) ->
catch collect_tests_from_file1(Specs,#testspec{nodes=NodeRefs},Relaxed).
collect_tests_from_file1([Spec|Specs],TestSpec,Relaxed) ->
+ SpecDir = filename:dirname(filename:absname(Spec)),
case file:consult(Spec) of
{ok,Terms} ->
- TestSpec1 = collect_tests(Terms,TestSpec,Relaxed),
+ TestSpec1 = collect_tests(Terms,TestSpec#testspec{spec_dir=SpecDir},
+ Relaxed),
collect_tests_from_file1(Specs,TestSpec1,Relaxed);
{error,Reason} ->
throw({error,{Spec,Reason}})
@@ -249,8 +251,11 @@ collect_tests_from_list(Terms,Relaxed) ->
collect_tests_from_list(Terms,[node()],Relaxed).
collect_tests_from_list(Terms,Nodes,Relaxed) when is_list(Nodes) ->
+ {ok,Cwd} = file:get_cwd(),
NodeRefs = lists:map(fun(N) -> {undefined,N} end, Nodes),
- case catch collect_tests(Terms,#testspec{nodes=NodeRefs},Relaxed) of
+ case catch collect_tests(Terms,#testspec{nodes=NodeRefs,
+ spec_dir=Cwd},
+ Relaxed) of
E = {error,_} ->
E;
TS ->
@@ -265,17 +270,51 @@ collect_tests(Terms,TestSpec,Relaxed) ->
put(relaxed,Relaxed),
TestSpec1 = get_global(Terms,TestSpec),
TestSpec2 = get_all_nodes(Terms,TestSpec1),
+ case catch evaluate(Terms,TestSpec2) of
+ {error,{Node,{M,F,A},Reason}} ->
+ io:format("Error! Common Test failed to evaluate ~w:~w/~w on ~w. "
+ "Reason: ~p~n~n", [M,F,A,Node,Reason]);
+ _ -> ok
+ end,
add_tests(Terms,TestSpec2).
+evaluate([{eval,NodeRef,{M,F,Args}}|Ts],Spec) ->
+ Node = ref2node(NodeRef,Spec#testspec.nodes),
+ case rpc:call(Node,M,F,Args) of
+ {badrpc,Reason} ->
+ throw({error,{Node,{M,F,length(Args)},Reason}});
+ _ ->
+ ok
+ end,
+ evaluate(Ts,Spec);
+evaluate([{eval,{M,F,Args}}|Ts],Spec) ->
+ case catch apply(M,F,Args) of
+ {'EXIT',Reason} ->
+ throw({error,{node(),{M,F,length(Args)},Reason}});
+ _ ->
+ ok
+ end,
+ evaluate(Ts,Spec);
+evaluate([],_Spec) ->
+ ok.
+
get_global([{alias,Ref,Dir}|Ts],Spec=#testspec{alias=Refs}) ->
- get_global(Ts,Spec#testspec{alias=[{Ref,get_absname(Dir)}|Refs]});
+ get_global(Ts,Spec#testspec{alias=[{Ref,get_absdir(Dir,Spec)}|Refs]});
get_global([{node,Ref,Node}|Ts],Spec=#testspec{nodes=Refs}) ->
get_global(Ts,Spec#testspec{nodes=[{Ref,Node}|lists:keydelete(Node,2,Refs)]});
get_global([_|Ts],Spec) -> get_global(Ts,Spec);
get_global([],Spec) -> Spec.
-get_absname(TestDir) ->
- AbsName = filename:absname(TestDir),
+get_absfile(FullName,#testspec{spec_dir=SpecDir}) ->
+ File = filename:basename(FullName),
+ Dir = get_absname(filename:dirname(FullName),SpecDir),
+ filename:join(Dir,File).
+
+get_absdir(Dir,#testspec{spec_dir=SpecDir}) ->
+ get_absname(Dir,SpecDir).
+
+get_absname(TestDir,SpecDir) ->
+ AbsName = filename:absname(TestDir,SpecDir),
TestDirName = filename:basename(AbsName),
Path = filename:dirname(AbsName),
TopDir = filename:basename(Path),
@@ -345,16 +384,17 @@ list_nodes(#testspec{nodes=NodeRefs}) ->
%% --- logdir ---
add_tests([{logdir,all_nodes,Dir}|Ts],Spec) ->
Dirs = Spec#testspec.logdir,
- Tests = [{logdir,N,Dir} || N <- list_nodes(Spec),
- lists:keymember(ref2node(N,Spec#testspec.nodes),
- 1,Dirs) == false],
+ Tests = [{logdir,N,get_absdir(Dir,Spec)} ||
+ N <- list_nodes(Spec),
+ lists:keymember(ref2node(N,Spec#testspec.nodes),
+ 1,Dirs) == false],
add_tests(Tests++Ts,Spec);
add_tests([{logdir,Nodes,Dir}|Ts],Spec) when is_list(Nodes) ->
Ts1 = separate(Nodes,logdir,[Dir],Ts,Spec#testspec.nodes),
add_tests(Ts1,Spec);
add_tests([{logdir,Node,Dir}|Ts],Spec) ->
Dirs = Spec#testspec.logdir,
- Dirs1 = [{ref2node(Node,Spec#testspec.nodes),Dir} |
+ Dirs1 = [{ref2node(Node,Spec#testspec.nodes),get_absdir(Dir,Spec)} |
lists:keydelete(ref2node(Node,Spec#testspec.nodes),1,Dirs)],
add_tests(Ts,Spec#testspec{logdir=Dirs1});
add_tests([{logdir,Dir}|Ts],Spec) ->
@@ -369,7 +409,7 @@ add_tests([{cover,Nodes,File}|Ts],Spec) when is_list(Nodes) ->
add_tests(Ts1,Spec);
add_tests([{cover,Node,File}|Ts],Spec) ->
CoverFs = Spec#testspec.cover,
- CoverFs1 = [{ref2node(Node,Spec#testspec.nodes),File} |
+ CoverFs1 = [{ref2node(Node,Spec#testspec.nodes),get_absfile(File,Spec)} |
lists:keydelete(ref2node(Node,Spec#testspec.nodes),1,CoverFs)],
add_tests(Ts,Spec#testspec{cover=CoverFs1});
add_tests([{cover,File}|Ts],Spec) ->
@@ -385,7 +425,8 @@ add_tests([{config,Nodes,Files}|Ts],Spec) when is_list(Nodes) ->
add_tests([{config,Node,[F|Fs]}|Ts],Spec) when is_list(F) ->
Cfgs = Spec#testspec.config,
Node1 = ref2node(Node,Spec#testspec.nodes),
- add_tests([{config,Node,Fs}|Ts],Spec#testspec{config=[{Node1,F}|Cfgs]});
+ add_tests([{config,Node,Fs}|Ts],
+ Spec#testspec{config=[{Node1,get_absfile(F,Spec)}|Cfgs]});
add_tests([{config,_Node,[]}|Ts],Spec) ->
add_tests(Ts,Spec);
add_tests([{config,Node,F}|Ts],Spec) ->
@@ -451,7 +492,8 @@ add_tests([{include,Nodes,InclDirs}|Ts],Spec) when is_list(Nodes) ->
add_tests([{include,Node,[D|Ds]}|Ts],Spec) when is_list(D) ->
Dirs = Spec#testspec.include,
Node1 = ref2node(Node,Spec#testspec.nodes),
- add_tests([{include,Node,Ds}|Ts],Spec#testspec{include=[{Node1,D}|Dirs]});
+ add_tests([{include,Node,Ds}|Ts],
+ Spec#testspec{include=[{Node1,get_absdir(D,Spec)}|Dirs]});
add_tests([{include,_Node,[]}|Ts],Spec) ->
add_tests(Ts,Spec);
add_tests([{include,Node,D}|Ts],Spec) ->
diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl
index 94ae2625cf..c1dc14f943 100644
--- a/lib/common_test/src/ct_util.hrl
+++ b/lib/common_test/src/ct_util.hrl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2003-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2003-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%
%%
@@ -27,7 +27,8 @@
address,
callback}).
--record(testspec, {nodes=[],
+-record(testspec, {spec_dir,
+ nodes=[],
logdir=["."],
cover=[],
config=[],
diff --git a/lib/common_test/src/unix_telnet.erl b/lib/common_test/src/unix_telnet.erl
index 14a70e9d22..25b9d4d5d2 100644
--- a/lib/common_test/src/unix_telnet.erl
+++ b/lib/common_test/src/unix_telnet.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% 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%
%%
@@ -23,10 +23,10 @@
%%% <p>It requires the following entry in the config file:</p>
%%% <pre>
%%% {unix,[{telnet,HostNameOrIpAddress},
-%%% {port,PortNum},
+%%% {port,PortNum}, % optional
%%% {username,UserName},
-%%% {password,Password}]}.
-%%% </pre>
+%%% {password,Password},
+%%% {keep_alive,Bool}]}. % optional</pre>
%%%
%%% <p>To talk telnet to the host specified by
%%% <code>HostNameOrIpAddress</code>, use the interface functions in
@@ -38,8 +38,14 @@
%%% <p>or</p>
%%% <pre> ct:require(Name,{unix,[telnet,username,password]}).</pre>
%%%
+%%% <p>The "keep alive" activity (i.e. that Common Test sends NOP to the server
+%%% every 10 seconds if the connection is idle) may be enabled or disabled for one
+%%% particular connection as described here. It may be disabled for all connections
+%%% using <c>telnet_settings</c> (see <c>ct_telnet</c>).</p>
+%%%
%%% <p>Note that the <code>{port,PortNum}</code> tuple is optional and if
-%%% omitted, default telnet port 23 will be used.</p>
+%%% omitted, default telnet port 23 will be used. Also the <c>keep_alive</c> tuple
+%%% is optional, and the value defauls to true (enabled).</p>
%%%
%%% @see ct
%%% @see ct_telnet
@@ -48,7 +54,7 @@
-compile(export_all).
%% Callbacks for ct_telnet.erl
--export([connect/4,get_prompt_regexp/0]).
+-export([connect/5,get_prompt_regexp/0]).
-import(ct_telnet,[start_log/1,cont_log/2,end_log/0]).
-define(username,"login: ").
@@ -70,10 +76,11 @@ get_prompt_regexp() ->
%%%-----------------------------------------------------------------
%%% @hidden
-%%% @spec connect(Ip,Port,Timeout,Extra) -> {ok,Handle} | {error,Reason}
+%%% @spec connect(Ip,Port,Timeout,KeepAlive,Extra) -> {ok,Handle} | {error,Reason}
%%% Ip = string() | {integer(),integer(),integer(),integer()}
%%% Port = integer()
%%% Timeout = integer()
+%%% KeepAlive = bool()
%%% Extra = {Username,Password}
%%% Username = string()
%%% Password = string()
@@ -82,23 +89,23 @@ get_prompt_regexp() ->
%%% @doc Callback for ct_telnet.erl.
%%%
%%% <p>Setup telnet connection to a UNIX host.</p>
-connect(Ip,Port,Timeout,Extra) ->
+connect(Ip,Port,Timeout,KeepAlive,Extra) ->
case Extra of
{Username,Password} ->
- connect(Ip,Port,Timeout,Username,Password);
+ connect1(Ip,Port,Timeout,KeepAlive,Username,Password);
Name ->
case get_username_and_password(Name) of
{ok,{Username,Password}} ->
- connect(Ip,Port,Timeout,Username,Password);
+ connect1(Ip,Port,Timeout,KeepAlive,Username,Password);
Error ->
Error
end
end.
-connect(Ip,Port,Timeout,Username,Password) ->
+connect1(Ip,Port,Timeout,KeepAlive,Username,Password) ->
start_log("unix_telnet:connect"),
Result =
- case ct_telnet_client:open(Ip,Port,Timeout) of
+ case ct_telnet_client:open(Ip,Port,Timeout,KeepAlive) of
{ok,Pid} ->
case ct_telnet:silent_teln_expect(Pid,[],[prompt],?prx,[]) of
{ok,{prompt,?username},_} ->
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
new file mode 100644
index 0000000000..35ba22aa59
--- /dev/null
+++ b/lib/common_test/test/Makefile
@@ -0,0 +1,94 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2008-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%
+#
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ ct_test_support \
+ ct_test_support_eh \
+ ct_smoke_test_SUITE \
+ ct_event_handler_SUITE \
+ ct_groups_test_1_SUITE \
+ ct_groups_test_2_SUITE \
+ ct_skip_SUITE \
+ ct_error_SUITE \
+ ct_test_server_if_1_SUITE
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+INSTALL_PROGS= $(TARGET_FILES)
+
+EMAKEFILE=Emakefile
+COVERFILE=
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/common_test_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ERL_MAKE_FLAGS += -pa $(ERL_TOP)/lib/test_server/ebin
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+
+EBIN = .
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+#.PHONY: make_emakefile
+
+#make_emakefile:
+# $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) \
+# '*_SUITE_make' > $(EMAKEFILE)
+# $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
+# >> $(EMAKEFILE)
+
+tests debug opt:
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f core
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+
+release_tests_spec:
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
+ $(INSTALL_PROGRAM) common_test.spec $(RELSYSDIR)
+ chmod -f -R u+w $(RELSYSDIR)
+ @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/lib/common_test/test/common_test.spec b/lib/common_test/test/common_test.spec
new file mode 100644
index 0000000000..7619a75b31
--- /dev/null
+++ b/lib/common_test/test/common_test.spec
@@ -0,0 +1 @@
+{topcase, {dir, "../common_test"}}.
diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl
new file mode 100644
index 0000000000..be75d768fc
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE.erl
@@ -0,0 +1,558 @@
+%%
+%% %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_error_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) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+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).
+
+all(doc) ->
+ [""];
+
+all(suite) ->
+ [
+ cfg_error,
+ lib_error,
+ no_compile
+ ].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+cfg_error(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suites = [Join(DataDir, "cfg_error_1_SUITE"),
+ Join(DataDir, "cfg_error_2_SUITE"),
+ Join(DataDir, "cfg_error_3_SUITE"),
+ Join(DataDir, "cfg_error_4_SUITE"),
+ Join(DataDir, "cfg_error_5_SUITE"),
+ Join(DataDir, "cfg_error_6_SUITE"),
+ Join(DataDir, "cfg_error_7_SUITE"),
+ Join(DataDir, "cfg_error_8_SUITE"),
+ Join(DataDir, "cfg_error_9_SUITE")
+ ],
+ {Opts,ERPid} = setup({suite,Suites}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(cfg_error,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(cfg_error),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%%
+lib_error(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suites = [Join(DataDir, "lib_error_1_SUITE")],
+ {Opts,ERPid} = setup({suite,Suites}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(lib_error,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(lib_error),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%%
+no_compile(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suites = [Join(DataDir, "no_compile_SUITE")],
+ {Opts,ERPid} = setup({suite,Suites}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(no_compile,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(no_compile),
+ 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 ++ [Test,{event_handler,{?eh,EvHArgs}}],
+ 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
+%%%-----------------------------------------------------------------
+test_events(cfg_error) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{9,9,33}},
+
+ {?eh,tc_start,{cfg_error_1_SUITE,init_per_suite}},
+ {?eh,tc_done,
+ {cfg_error_1_SUITE,init_per_suite,{failed,{error,init_per_suite_fails}}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_1_SUITE,tc1,{failed,{cfg_error_1_SUITE,init_per_suite,
+ {'EXIT',init_per_suite_fails}}}}},
+ {?eh,test_stats,{0,0,{0,1}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_1_SUITE,tc2,{failed,{cfg_error_1_SUITE,init_per_suite,
+ {'EXIT',init_per_suite_fails}}}}},
+ {?eh,test_stats,{0,0,{0,2}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_1_SUITE,end_per_suite,{failed,{cfg_error_1_SUITE,init_per_suite,
+ {'EXIT',init_per_suite_fails}}}}},
+
+ {?eh,tc_start,{cfg_error_2_SUITE,init_per_suite}},
+ {?eh,tc_done,
+ {cfg_error_2_SUITE,init_per_suite,
+ {failed,{error,{{badmatch,[1,2]},
+ [{cfg_error_2_SUITE,init_per_suite,1},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_2_SUITE,tc1,
+ {failed,{cfg_error_2_SUITE,init_per_suite,
+ {'EXIT',{{badmatch,[1,2]},
+ [{cfg_error_2_SUITE,init_per_suite,1},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}}},
+ {?eh,test_stats,{0,0,{0,3}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_2_SUITE,tc2,
+ {failed,{cfg_error_2_SUITE,init_per_suite,
+ {'EXIT',{{badmatch,[1,2]},
+ [{cfg_error_2_SUITE,init_per_suite,1},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}}},
+ {?eh,test_stats,{0,0,{0,4}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_2_SUITE,end_per_suite,
+ {failed,{cfg_error_2_SUITE,init_per_suite,
+ {'EXIT',{{badmatch,[1,2]},
+ [{cfg_error_2_SUITE,init_per_suite,1},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}}},
+
+ {?eh,tc_start,{cfg_error_3_SUITE,init_per_suite}},
+ {?eh,tc_done,
+ {cfg_error_3_SUITE,init_per_suite,{failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_3_SUITE,tc1,
+ {failed,{cfg_error_3_SUITE,init_per_suite,{timetrap_timeout,2000}}}}},
+ {?eh,test_stats,{0,0,{0,5}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_3_SUITE,tc2,
+ {failed,{cfg_error_3_SUITE,init_per_suite,{timetrap_timeout,2000}}}}},
+ {?eh,test_stats,{0,0,{0,6}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_3_SUITE,end_per_suite,
+ {failed,{cfg_error_3_SUITE,init_per_suite,{timetrap_timeout,2000}}}}},
+
+ {?eh,tc_start,{cfg_error_4_SUITE,init_per_suite}},
+ {?eh,tc_done,{cfg_error_4_SUITE,init_per_suite,ok}},
+ {?eh,tc_auto_skip,
+ {cfg_error_4_SUITE,tc1,
+ {failed,{cfg_error_4_SUITE,init_per_suite,bad_return}}}},
+ {?eh,test_stats,{0,0,{0,7}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_4_SUITE,tc2,
+ {failed,{cfg_error_4_SUITE,init_per_suite,bad_return}}}},
+ {?eh,test_stats,{0,0,{0,8}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_4_SUITE,end_per_suite,
+ {failed,{cfg_error_4_SUITE,init_per_suite,bad_return}}}},
+
+ {?eh,tc_start,{cfg_error_5_SUITE,init_per_suite}},
+ {?eh,tc_done,{cfg_error_5_SUITE,init_per_suite,ok}},
+ {?eh,tc_auto_skip,
+ {cfg_error_5_SUITE,tc1,
+ {failed,{cfg_error_5_SUITE,init_per_suite,bad_return}}}},
+ {?eh,test_stats,{0,0,{0,9}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_5_SUITE,tc2,
+ {failed,{cfg_error_5_SUITE,init_per_suite,bad_return}}}},
+ {?eh,test_stats,{0,0,{0,10}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_5_SUITE,end_per_suite,
+ {failed,{cfg_error_5_SUITE,init_per_suite,bad_return}}}},
+
+ {?eh,tc_start,{cfg_error_6_SUITE,init_per_suite}},
+ {?eh,tc_done,{cfg_error_6_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{cfg_error_6_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_6_SUITE,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,10}}},
+ [{?eh,tc_start,{cfg_error_6_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{cfg_error_6_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_start,{cfg_error_6_SUITE,tc2}},
+ {?eh,tc_done,{cfg_error_6_SUITE,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,10}}},
+ {?eh,tc_start,{cfg_error_6_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{cfg_error_6_SUITE,{end_per_group,g1,[]},ok}}],
+ {?eh,tc_start,{cfg_error_6_SUITE,end_per_suite}},
+ {?eh,tc_done,{cfg_error_6_SUITE,end_per_suite,
+ {failed,{error,{{badmatch,[1,2]},
+ [{cfg_error_6_SUITE,end_per_suite,1},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}},
+
+ {?eh,tc_start,{cfg_error_7_SUITE,init_per_suite}},
+ {?eh,tc_done,{cfg_error_7_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{cfg_error_7_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_7_SUITE,tc1,ok}},
+ {?eh,test_stats,{3,0,{0,10}}},
+ [{?eh,tc_start,{cfg_error_7_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{cfg_error_7_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_start,{cfg_error_7_SUITE,tc2}},
+ {?eh,tc_done,{cfg_error_7_SUITE,tc2,ok}},
+ {?eh,test_stats,{4,0,{0,10}}},
+ {?eh,tc_start,{cfg_error_7_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{cfg_error_7_SUITE,{end_per_group,g1,[]},ok}}],
+ {?eh,tc_start,{cfg_error_7_SUITE,end_per_suite}},
+ {?eh,tc_done,
+ {cfg_error_7_SUITE,end_per_suite,{failed,{timetrap_timeout,2000}}}},
+
+ {?eh,tc_start,{cfg_error_8_SUITE,init_per_suite}},
+ {?eh,tc_done,{cfg_error_8_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,
+ {cfg_error_8_SUITE,{init_per_group,g1,[]},
+ {failed,{error,{init_per_group_fails,g1}}}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_8_SUITE,tc1,
+ {failed,{cfg_error_8_SUITE,init_per_group,
+ {'EXIT',{init_per_group_fails,g1}}}}}},
+ {?eh,test_stats,{4,0,{0,11}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_8_SUITE,end_per_group,
+ {failed,{cfg_error_8_SUITE,init_per_group,
+ {'EXIT',{init_per_group_fails,g1}}}}}}],
+
+ [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,
+ {init_per_group,unknown,[]},
+ {failed,{timetrap_timeout,2000}}}},
+ {?eh,tc_auto_skip,{cfg_error_8_SUITE,tc1,
+ {failed,{cfg_error_8_SUITE,init_per_group,
+ {timetrap_timeout,2000}}}}},
+ {?eh,test_stats,{4,0,{0,12}}},
+ {?eh,tc_auto_skip,{cfg_error_8_SUITE,end_per_group,
+ {failed,{cfg_error_8_SUITE,init_per_group,
+ {timetrap_timeout,2000}}}}}],
+
+ [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,
+ {cfg_error_8_SUITE,{init_per_group,g3,[]},
+ {failed,{error,{{badmatch,42},
+ [{cfg_error_8_SUITE,init_per_group,2},
+ {cfg_error_8_SUITE,init_per_group,2},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_8_SUITE,tc1,
+ {failed,{cfg_error_8_SUITE,init_per_group,
+ {'EXIT',{{badmatch,42},
+ [{cfg_error_8_SUITE,init_per_group,2},
+ {cfg_error_8_SUITE,init_per_group,2},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}}},
+ {?eh,test_stats,{4,0,{0,13}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_8_SUITE,end_per_group,
+ {failed,{cfg_error_8_SUITE,init_per_group,
+ {'EXIT',{{badmatch,42},
+ [{cfg_error_8_SUITE,init_per_group,2},
+ {cfg_error_8_SUITE,init_per_group,2},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}}}],
+
+ [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g4,[]},ok}},
+ {?eh,tc_start,{cfg_error_8_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_8_SUITE,tc1,ok}},
+ {?eh,test_stats,{5,0,{0,13}}},
+ {?eh,tc_start,{cfg_error_8_SUITE,{end_per_group,g4,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{end_per_group,g4,[]},ok}}],
+
+ [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g5,[]},ok}},
+ {?eh,tc_start,{cfg_error_8_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_8_SUITE,tc1,ok}},
+ {?eh,test_stats,{6,0,{0,13}}},
+ [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g6,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g6,[]},
+ {failed,{error,{sub_group_failed,g6}}}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_8_SUITE,tc2,
+ {failed,{cfg_error_8_SUITE,init_per_group,
+ {'EXIT',{sub_group_failed,g6}}}}}},
+ {?eh,test_stats,{6,0,{0,14}}},
+ {?eh,tc_auto_skip,
+ {cfg_error_8_SUITE,end_per_group,
+ {failed,{cfg_error_8_SUITE,init_per_group,
+ {'EXIT',{sub_group_failed,g6}}}}}}],
+ {?eh,tc_start,{cfg_error_8_SUITE,tc3}},
+ {?eh,tc_done,{cfg_error_8_SUITE,tc3,ok}},
+ {?eh,test_stats,{7,0,{0,14}}},
+ {?eh,tc_start,{cfg_error_8_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{end_per_group,g5,[]},ok}}],
+
+ [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g11,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g11,[]},ok}},
+ {?eh,tc_start,{cfg_error_8_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_8_SUITE,tc1,ok}},
+ {?eh,test_stats,{8,0,{0,14}}},
+ {?eh,tc_start,{cfg_error_8_SUITE,{end_per_group,g11,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{end_per_group,g11,[]},
+ {failed,{error,{end_per_group_fails,g5}}}}}],
+
+ [{?eh,tc_start,{cfg_error_8_SUITE,{init_per_group,g12,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{init_per_group,g12,[]},ok}},
+ {?eh,tc_start,{cfg_error_8_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_8_SUITE,tc1,ok}},
+ {?eh,test_stats,{9,0,{0,14}}},
+ {?eh,tc_start,{cfg_error_8_SUITE,{end_per_group,g12,[]}}},
+ {?eh,tc_done,{cfg_error_8_SUITE,{end_per_group,unknown,[]},
+ {failed,{timetrap_timeout,2000}}}}],
+
+ {?eh,tc_start,{cfg_error_8_SUITE,end_per_suite}},
+ {?eh,tc_done,{cfg_error_8_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{cfg_error_9_SUITE,init_per_suite}},
+ {?eh,tc_done,{cfg_error_9_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_9_SUITE,tc1,
+ {skipped,{failed,{cfg_error_9_SUITE,init_per_testcase,
+ tc1_should_be_skipped}}}}},
+ {?eh,test_stats,{9,0,{0,15}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc2}},
+ {?eh,tc_done,{cfg_error_9_SUITE,tc2,
+ {skipped,{failed,{cfg_error_9_SUITE,init_per_testcase,
+ {timetrap_timeout,2000}}}}}},
+ {?eh,test_stats,{9,0,{0,16}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc3}},
+ {?eh,tc_done,{cfg_error_9_SUITE,tc3,
+ {skipped,{failed,{cfg_error_9_SUITE,init_per_testcase,
+ {{badmatch,undefined},
+ [{cfg_error_9_SUITE,init_per_testcase,2},
+ {test_server,my_apply,3},
+ {test_server,init_per_testcase,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}}},
+ {?eh,test_stats,{9,0,{0,17}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc4}},
+ {?eh,tc_done,
+ {cfg_error_9_SUITE,tc4,
+ {skipped,{failed,{cfg_error_9_SUITE,init_per_testcase,bad_return}}}}},
+ {?eh,test_stats,{9,0,{0,18}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc5}},
+ {?eh,tc_done,
+ {cfg_error_9_SUITE,tc5,{failed,{error,fail_this_testcase}}}},
+ {?eh,test_stats,{9,1,{0,18}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc6}},
+ %%! we get ok with tc_done since it's only afterwards
+ %%! end_tc failes the testcase
+ {?eh,tc_done,{cfg_error_9_SUITE,tc6,ok}},
+ {?eh,test_stats,{9,2,{0,18}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc11}},
+ {?eh,tc_done,{cfg_error_9_SUITE,tc11,
+ {failed,{cfg_error_9_SUITE,end_per_testcase,
+ {'EXIT',warning_should_be_printed}}}}},
+ {?eh,test_stats,{10,2,{0,18}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc12}},
+ {?eh,tc_done,{cfg_error_9_SUITE,tc12,
+ {failed,{cfg_error_9_SUITE,end_per_testcase,
+ {timetrap_timeout,2000}}}}},
+ {?eh,test_stats,{11,2,{0,18}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc13}},
+ {?eh,tc_done,{cfg_error_9_SUITE,tc13,
+ {failed,{cfg_error_9_SUITE,end_per_testcase,
+ {'EXIT',{{badmatch,undefined},
+ [{cfg_error_9_SUITE,end_per_testcase,2},
+ {test_server,my_apply,3},
+ {test_server,do_end_per_testcase,4},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}}},
+ {?eh,test_stats,{12,2,{0,18}}},
+ {?eh,tc_start,{cfg_error_9_SUITE,tc14}},
+ {?eh,tc_done,
+ {cfg_error_9_SUITE,tc14,{failed,{error,tc14_should_be_failed}}}},
+ {?eh,test_stats,{12,3,{0,18}}},
+
+ {?eh,tc_start,{cfg_error_9_SUITE,end_per_suite}},
+ {?eh,tc_done,{cfg_error_9_SUITE,end_per_suite,ok}},
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(lib_error) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,14}},
+ {?eh,tc_start,{lib_error_1_SUITE,init_per_suite}},
+ {?eh,tc_done,{lib_error_1_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{lib_error_1_SUITE,lines_error}},
+ {?eh,tc_done,
+ {lib_error_1_SUITE,lines_error,{failed,
+ {error,
+ {{badmatch,[1,2]},
+ [{lib_lines,do_error,0},
+ {lib_error_1_SUITE,lines_error,1},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,lines_exit}},
+ {?eh,tc_done,
+ {lib_error_1_SUITE,lines_exit,{failed,{error,byebye}}}},
+ {?eh,test_stats,{0,2,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,lines_hang}},
+ {?eh,tc_done,
+ {lib_lines,do_hang,{failed,{timetrap_timeout,3000}}}},
+ {?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,lines_throw}},
+ {?eh,tc_done,
+ {lib_error_1_SUITE,lines_throw,
+ {failed,{error,{thrown,catch_me_if_u_can}}}}},
+ {?eh,test_stats,{0,4,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,no_lines_error}},
+ {?eh,tc_done,
+ {lib_error_1_SUITE,no_lines_error,{failed,
+ {error,
+ {{badmatch,[1,2]},
+ [{lib_no_lines,do_error,0},
+ {lib_error_1_SUITE,no_lines_error,1},
+ {test_server,my_apply,3},
+ {test_server,ts_tc,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}},
+ {?eh,test_stats,{0,5,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,no_lines_exit}},
+ {?eh,tc_done,
+ {lib_error_1_SUITE,no_lines_exit,{failed,{error,byebye}}}},
+ {?eh,test_stats,{0,6,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,no_lines_hang}},
+ {?eh,tc_done,
+ {lib_error_1_SUITE,no_lines_hang,{failed,{timetrap_timeout,3000}}}},
+ {?eh,test_stats,{0,7,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,no_lines_throw}},
+ {?eh,tc_done,
+ {lib_error_1_SUITE,no_lines_throw,{failed,{error,{thrown,catch_me_if_u_can}}}}},
+ {?eh,test_stats,{0,8,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,init_tc_error}},
+ {?eh,tc_done,{lib_error_1_SUITE,init_tc_error,ok}},
+ {?eh,test_stats,{1,8,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,init_tc_exit}},
+ {?eh,tc_done,{lib_error_1_SUITE,init_tc_exit,ok}},
+ {?eh,test_stats,{2,8,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,init_tc_throw}},
+ {?eh,tc_done,{lib_error_1_SUITE,init_tc_throw,ok}},
+ {?eh,test_stats,{3,8,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,end_tc_error}},
+ {?eh,tc_done,{lib_error_1_SUITE,end_tc_error,ok}},
+ {?eh,test_stats,{3,9,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,end_tc_exit}},
+ {?eh,tc_done,{lib_error_1_SUITE,end_tc_exit,ok}},
+ {?eh,test_stats,{3,10,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,end_tc_throw}},
+ {?eh,tc_done,{lib_error_1_SUITE,end_tc_throw,ok}},
+ {?eh,test_stats,{3,11,{0,0}}},
+ {?eh,tc_start,{lib_error_1_SUITE,end_per_suite}},
+ {?eh,tc_done,{lib_error_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(no_compile) ->
+ [].
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_1_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_1_SUITE.erl
new file mode 100644
index 0000000000..a9649be9e0
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_1_SUITE.erl
@@ -0,0 +1,116 @@
+%%
+%% %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%
+%%
+-module(cfg_error_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,3}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ exit(init_per_suite_fails),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,{group,g1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_2_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_2_SUITE.erl
new file mode 100644
index 0000000000..a02090a5e8
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_2_SUITE.erl
@@ -0,0 +1,117 @@
+%%
+%% %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%
+%%
+-module(cfg_error_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,3}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ ct:comment(init_per_suite_fails),
+ ok = lists:seq(1,2),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,{group,g1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_3_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_3_SUITE.erl
new file mode 100644
index 0000000000..bf01bb52d9
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_3_SUITE.erl
@@ -0,0 +1,116 @@
+%%
+%% %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%
+%%
+-module(cfg_error_3_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ timer:sleep(5000),
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,{group,g1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_4_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_4_SUITE.erl
new file mode 100644
index 0000000000..aaf29df65f
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_4_SUITE.erl
@@ -0,0 +1,115 @@
+%%
+%% %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%
+%%
+-module(cfg_error_4_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,{group,g1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_5_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_5_SUITE.erl
new file mode 100644
index 0000000000..b421f7d809
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_5_SUITE.erl
@@ -0,0 +1,115 @@
+%%
+%% %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%
+%%
+-module(cfg_error_5_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ [bad_data | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,{group,g1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_6_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_6_SUITE.erl
new file mode 100644
index 0000000000..370ac0839b
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_6_SUITE.erl
@@ -0,0 +1,116 @@
+%%
+%% %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%
+%%
+-module(cfg_error_6_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ ct:comment("this should fail"),
+ badmatch = lists:seq(1,2).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,{group,g1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_7_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_7_SUITE.erl
new file mode 100644
index 0000000000..9cd5b6ad29
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_7_SUITE.erl
@@ -0,0 +1,116 @@
+%%
+%% %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%
+%%
+-module(cfg_error_7_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ timer:sleep(5000),
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,{group,g1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_8_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_8_SUITE.erl
new file mode 100644
index 0000000000..25993833d7
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_8_SUITE.erl
@@ -0,0 +1,152 @@
+%%
+%% %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%
+%%
+-module(cfg_error_8_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(g1, Config) ->
+ exit({init_per_group_fails,g1}),
+ Config;
+init_per_group(g2, Config) ->
+ ct:comment("init_per_group(g2) timeout"),
+ timer:sleep(5000),
+ Config;
+init_per_group(g3, _Config) ->
+ badmatch = 42;
+init_per_group(g4, _Config) ->
+ ok;
+init_per_group(g6, Config) ->
+ exit({sub_group_failed,g6}),
+ Config;
+init_per_group(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(g11, _Config) ->
+ exit({end_per_group_fails,g5}),
+ ok;
+end_per_group(g12, _Config) ->
+ ct:comment("end_per_group(g6) timeout"),
+ timer:sleep(5000),
+ ok;
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc1]},
+ {g2,[],[tc1]},
+ {g3,[],[tc1]},
+ {g4,[],[tc1]},
+ {g5,[],[tc1,{g6,[],[tc2]},tc3]},
+ {g11,[],[tc1]},
+ {g12,[],[tc1]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [{group,g1},
+ {group,g2},
+ {group,g3},
+ {group,g4},
+ {group,g5},
+ {group,g11},
+ {group,g12}
+ ].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
+
+tc3(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl
new file mode 100644
index 0000000000..d73287ad62
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_9_SUITE.erl
@@ -0,0 +1,185 @@
+%%
+%% %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%
+%%
+-module(cfg_error_9_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(tc1, Config) ->
+ exit(tc1_should_be_skipped),
+ Config;
+init_per_testcase(tc2, Config) ->
+ ct:comment("init_per_testcase(tc2) timeout"),
+ timer:sleep(5000),
+ Config;
+init_per_testcase(tc3, Config) ->
+ badmatch = ?config(void, Config),
+ Config;
+init_per_testcase(tc4, _) ->
+ ok;
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(tc11, _Config) ->
+ ct:comment("A warning should be printed"),
+ exit(warning_should_be_printed),
+ done;
+end_per_testcase(tc12, _Config) ->
+ ct:comment("A warning should be printed"),
+ timer:sleep(5000),
+ done;
+end_per_testcase(tc13, Config) ->
+ ct:comment("A warning should be printed"),
+ badmatch = ?config(void, Config),
+ done;
+end_per_testcase(tc14, Config) ->
+ ok = ?config(tc_status, Config),
+ {fail,tc14_should_be_failed};
+end_per_testcase(tc15, Config) ->
+ {failed,byebye} = ?config(tc_status, Config),
+ ok;
+end_per_testcase(_TestCase, _Config) ->
+ done.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2,tc3,tc4,tc5,tc6,
+ tc11,tc12,tc13,tc14].
+
+tc1(_) ->
+ fini.
+tc2(_) ->
+ fini.
+tc3(_) ->
+ fini.
+tc4(_) ->
+ fini.
+
+
+tc5() ->
+ put('$test_server_framework_test',
+ fun(init_tc, _Default) -> {fail,fail_this_testcase};
+ (_, Default) -> Default
+ end),
+ [].
+
+tc5(_) ->
+ ct:comment("This one should get failed by init_tc!"),
+ fini.
+
+tc6() ->
+ put('$test_server_framework_test',
+ fun(end_tc, _Default) -> {fail,fail_this_testcase};
+ (_, Default) -> Default
+ end),
+ [].
+
+tc6(_) ->
+ ct:comment("This one should succeed but then get failed by end_tc!"),
+ fini.
+
+tc11(_) ->
+ fini.
+tc12(_) ->
+ ct:comment("It's ok if this doesn't get printed"),
+ fini.
+tc13(_) ->
+ fini.
+tc14(_) ->
+ ct:comment("This one should be failed by eptc"),
+ yes.
+tc15(_) ->
+ exit(byebye).
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/lib_error_1_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/lib_error_1_SUITE.erl
new file mode 100644
index 0000000000..6e6f83949d
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/lib_error_1_SUITE.erl
@@ -0,0 +1,188 @@
+%%
+%% %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%
+%%
+-module(lib_error_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,3}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [lines_error, lines_exit, lines_hang, lines_throw,
+ no_lines_error, no_lines_exit, no_lines_hang, no_lines_throw,
+ init_tc_error, init_tc_exit, init_tc_throw,
+ end_tc_error, end_tc_exit, end_tc_throw].
+
+lines_error(_) ->
+ io:format("Calling lib function..."),
+ lib_lines:do_error(),
+ ok.
+
+lines_exit(_) ->
+ io:format("Calling lib function..."),
+ lib_lines:do_exit(),
+ ok.
+
+lines_hang(_) ->
+ io:format("Calling lib function..."),
+ lib_lines:do_hang(),
+ ok.
+
+lines_throw(_) ->
+ io:format("Calling lib function..."),
+ lib_lines:do_throw(),
+ ok.
+
+no_lines_error(_) ->
+ io:format("Calling lib function..."),
+ lib_no_lines:do_error(),
+ ok.
+
+no_lines_exit(_) ->
+ io:format("Calling lib function..."),
+ lib_no_lines:do_exit(),
+ ok.
+
+no_lines_hang(_) ->
+ io:format("Calling lib function..."),
+ lib_no_lines:do_hang(),
+ ok.
+
+no_lines_throw(_) ->
+ io:format("Calling lib function..."),
+ lib_no_lines:do_throw(),
+ ok.
+
+init_tc_error(_) ->
+ put('$test_server_framework_test',
+ fun(init_tc, _Default) -> lib_no_lines:do_error(), ok;
+ (_, Default) -> Default
+ end), ok.
+
+init_tc_exit(_) ->
+ put('$test_server_framework_test',
+ fun(init_tc, _Default) -> lib_no_lines:do_exit(), ok;
+ (_, Default) -> Default
+ end), ok.
+
+init_tc_throw(_) ->
+ put('$test_server_framework_test',
+ fun(init_tc, _Default) -> lib_no_lines:do_throw(), ok;
+ (_, Default) -> Default
+ end), ok.
+
+end_tc_error(_) ->
+ put('$test_server_framework_test',
+ fun(end_tc, _Default) -> lib_no_lines:do_error(), ok;
+ (_, Default) -> Default
+ end), ok.
+
+end_tc_exit(_) ->
+ put('$test_server_framework_test',
+ fun(end_tc, _Default) -> lib_no_lines:do_exit(), ok;
+ (_, Default) -> Default
+ end), ok.
+
+end_tc_throw(_) ->
+ put('$test_server_framework_test',
+ fun(end_tc, _Default) -> lib_no_lines:do_throw(), ok;
+ (_, Default) -> Default
+ end), ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/lib_lines.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/lib_lines.erl
new file mode 100644
index 0000000000..b8f5814004
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/lib_lines.erl
@@ -0,0 +1,25 @@
+-module(lib_lines).
+
+-export([do_error/0, do_exit/0, do_hang/0, do_throw/0]).
+
+-include("ct.hrl").
+
+do_error() ->
+ io:format("Here comes an error...~n"),
+ [] = lists:seq(1,2),
+ ok.
+
+do_exit() ->
+ io:format("Here comes an exit...~n"),
+ exit(byebye),
+ ok.
+
+do_hang() ->
+ io:format("Here comes a hang...~n"),
+ receive after infinity -> ok end,
+ ok.
+
+do_throw() ->
+ io:format("Here comes a throw...~n"),
+ throw(catch_me_if_u_can),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/lib_no_lines.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/lib_no_lines.erl
new file mode 100644
index 0000000000..4d2b08be03
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/lib_no_lines.erl
@@ -0,0 +1,23 @@
+-module(lib_no_lines).
+
+-export([do_error/0, do_exit/0, do_hang/0, do_throw/0]).
+
+do_error() ->
+ io:format("Here comes a badmatch error...~n"),
+ [] = lists:seq(1,2),
+ ok.
+
+do_exit() ->
+ io:format("Here comes a byebye exit...~n"),
+ exit(byebye),
+ ok.
+
+do_hang() ->
+ io:format("Here comes a hang...~n"),
+ receive after infinity -> ok end,
+ ok.
+
+do_throw() ->
+ io:format("Here comes a throw...~n"),
+ throw(catch_me_if_u_can),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/no_compile_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/no_compile_SUITE.erl
new file mode 100644
index 0000000000..534a8f34af
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/no_compile_SUITE.erl
@@ -0,0 +1,115 @@
+%%
+%% %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%
+%%
+-module(no_compile_SUITE).
+
+-compile(export_all).
+
+-include("ct.hrl")
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,{group,g1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_event_handler_SUITE.erl b/lib/common_test/test/ct_event_handler_SUITE.erl
new file mode 100644
index 0000000000..bafd32f937
--- /dev/null
+++ b/lib/common_test/test/ct_event_handler_SUITE.erl
@@ -0,0 +1,170 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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_event_handler_SUITE.erl
+%%%
+%%% Description: This suite will install event handlers and run
+%%% some simple tests to check that events are generated according
+%%% to the specification (see Event Handling in CT User's Guide).
+%%%-------------------------------------------------------------------
+-module(ct_event_handler_SUITE).
+
+-compile(export_all).
+
+-include_lib("test_server/include/test_server.hrl").
+
+%-include_lib("common_test/include/ct_event.hrl").
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+
+ EH = filename:join(DataDir, "eh_A.erl"),
+ CResult = compile:file(EH, [verbose,report,{outdir,PrivDir}]),
+ test_server:format("~s compilation result: ~p~n", [EH,CResult]),
+
+ Config1 = ct_test_support:init_per_suite(Config, 0),
+ Config1.
+
+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).
+
+all(doc) ->
+ [];
+
+all(suite) ->
+ [start_stop, results].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+start_stop(doc) ->
+ [];
+
+start_stop(suite) ->
+ [];
+
+start_stop(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ TestObj = filename:join(DataDir, "event_handling_1"),
+ Suite1 = filename:join(TestObj, "test/eh_11_SUITE"),
+ Opts0 = ct_test_support:get_opts(Config),
+
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+
+ Opts = Opts0 ++ [{suite,Suite1},{testcase,tc1},
+ {event_handler,{eh_A,EvHArgs}}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(start_stop,
+ ct_test_support:reformat(Events, eh_A),
+ ?config(priv_dir, Config)),
+
+ TestEvents =
+ [{eh_A,start_logging,{'DEF','RUNDIR'}},
+ {eh_A,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {eh_A,start_info,{1,1,1}},
+ {eh_A,tc_start,{eh_11_SUITE,init_per_suite}},
+ {eh_A,tc_done,{eh_11_SUITE,init_per_suite,ok}},
+ {eh_A,tc_start,{eh_11_SUITE,tc1}},
+ {eh_A,tc_done,{eh_11_SUITE,tc1,ok}},
+ {eh_A,test_stats,{1,0,{0,0}}},
+ {eh_A,tc_start,{eh_11_SUITE,end_per_suite}},
+ {eh_A,tc_done,{eh_11_SUITE,end_per_suite,ok}},
+ {eh_A,test_done,{'DEF','STOP_TIME'}},
+ {eh_A,stop_logging,[]}],
+
+ ok = ct_test_support:verify_events(TestEvents, Events, Config),
+ {comment,"NOTE! Known problem with test_start event!"}.
+
+
+results(doc) ->
+ [];
+
+results(suite) ->
+ [];
+
+results(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ TestObj = filename:join(DataDir, "event_handling_1"),
+ Suite1 = filename:join(TestObj, "test/eh_11_SUITE"),
+ Opts0 = ct_test_support:get_opts(Config),
+
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+
+ Opts = Opts0 ++ [{suite,Suite1},
+ {event_handler,{eh_A,EvHArgs}}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(results,
+ ct_test_support:reformat(Events, eh_A),
+ ?config(priv_dir, Config)),
+
+ TestEvents =
+ [{eh_A,start_logging,{'DEF','RUNDIR'}},
+ {eh_A,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {eh_A,start_info,{1,1,3}},
+ {eh_A,tc_start,{eh_11_SUITE,init_per_suite}},
+ {eh_A,tc_done,{eh_11_SUITE,init_per_suite,ok}},
+ {eh_A,tc_start,{eh_11_SUITE,tc1}},
+ {eh_A,tc_done,{eh_11_SUITE,tc1,ok}},
+ {eh_A,test_stats,{1,0,{0,0}}},
+ {eh_A,tc_start,{eh_11_SUITE,tc2}},
+ {eh_A,tc_done,{eh_11_SUITE,tc2,{skipped,"Skipped"}}},
+ {eh_A,test_stats,{1,0,{1,0}}},
+ {eh_A,tc_start,{eh_11_SUITE,tc3}},
+ {eh_A,tc_done,{eh_11_SUITE,tc3,{failed,{error,'Failing'}}}},
+ {eh_A,test_stats,{1,1,{1,0}}},
+ {eh_A,tc_start,{eh_11_SUITE,end_per_suite}},
+ {eh_A,tc_done,{eh_11_SUITE,end_per_suite,ok}},
+ {eh_A,test_done,{'DEF','STOP_TIME'}},
+ {eh_A,stop_logging,[]}],
+
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
diff --git a/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl b/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
new file mode 100644
index 0000000000..6e526f15a2
--- /dev/null
+++ b/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
@@ -0,0 +1,127 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. 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 Event handler module
+%%%
+%%% <p>This is an event handler module used for testing that
+%%% Common Test generates events as expected.</p>
+%%%
+-module(eh_A).
+
+-behaviour(gen_event).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+%% gen_event callbacks
+-export([init/1, handle_event/2, handle_call/2,
+ handle_info/2, terminate/2, code_change/3]).
+
+-record(state, {cbm=ct_test_support,
+ trace_level=50}).
+
+%%====================================================================
+%% gen_event callbacks
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State}
+%% Description: Whenever a new event handler is added to an event manager,
+%% this function is called to initialize the event handler.
+%%--------------------------------------------------------------------
+init(Args) ->
+
+ S1 = case lists:keysearch(cbm, 1, Args) of
+ {_,{cbm,CBM}} ->
+ #state{cbm=CBM};
+ _ ->
+ #state{}
+ end,
+ S2 = case lists:keysearch(trace_level, 1, Args) of
+ {_,{trace_level,Level}} ->
+ S1#state{trace_level=Level};
+ _ ->
+ S1
+ end,
+ print(S2#state.trace_level, "Event Handler ~w started!~n", [?MODULE]),
+ {ok,S2}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_event(Event, State) -> {ok, State} |
+%% {swap_handler, Args1, State1, Mod2, Args2} |
+%% remove_handler
+%% Description:Whenever an event manager receives an event sent using
+%% gen_event:notify/2 or gen_event:sync_notify/2, this function is called for
+%% each installed event handler to handle the event.
+%%--------------------------------------------------------------------
+handle_event(Event, State=#state{cbm=CBM, trace_level=_Level}) ->
+ % print(_Level, "~p: ~p~n", [Event#event.name,Event#event.data]),
+ CBM:handle_event(?MODULE, Event),
+ {ok,State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_call(Request, State) -> {ok, Reply, State} |
+%% {swap_handler, Reply, Args1, State1,
+%% Mod2, Args2} |
+%% {remove_handler, Reply}
+%% Description: Whenever an event manager receives a request sent using
+%% gen_event:call/3,4, this function is called for the specified event
+%% handler to handle the request.
+%%--------------------------------------------------------------------
+handle_call(_Req, State) ->
+ Reply = ok,
+ {ok, Reply, State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_info(Info, State) -> {ok, State} |
+%% {swap_handler, Args1, State1, Mod2, Args2} |
+%% remove_handler
+%% Description: This function is called for each installed event handler when
+%% an event manager receives any other message than an event or a synchronous
+%% request (or a system message).
+%%--------------------------------------------------------------------
+handle_info(_Info, State) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description:Whenever an event handler is deleted from an event manager,
+%% this function is called. It should be the opposite of Module:init/1 and
+%% do any necessary cleaning up.
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+print(Level, _Str, _Args) ->
+ test_server:format(Level, _Str,_Args).
+
+
diff --git a/lib/common_test/test/ct_event_handler_SUITE_data/event_handling_1/test/eh_11_SUITE.erl b/lib/common_test/test/ct_event_handler_SUITE_data/event_handling_1/test/eh_11_SUITE.erl
new file mode 100644
index 0000000000..16b7129993
--- /dev/null
+++ b/lib/common_test/test/ct_event_handler_SUITE_data/event_handling_1/test/eh_11_SUITE.erl
@@ -0,0 +1,141 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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 : eh_11_SUITE.erl
+%%% Description : Used by ct_event_handler_SUITE to test event handling.
+%%%-------------------------------------------------------------------
+-module(eh_11_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% COMMON TEST CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%%
+%% Info = [tuple()]
+%% List of key/value pairs.
+%%
+%% Description: Returns list of tuples to set default properties
+%% for the suite.
+%%
+%% Note: The suite/0 function is only meant to be used to return
+%% default data values, not perform any other operations.
+%%--------------------------------------------------------------------
+suite() ->
+ [
+ {timetrap,{seconds,10}}
+ ].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the suite.
+%%
+%% Description: Initialization before the suite.
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after the suite.
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%%
+%% TestCase = atom()
+%% Name of the test case that is about to run.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Initialization 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.
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%%
+%% TestCase = atom()
+%% Name of the test case that is finished.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after each test case.
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: all() -> TestCases | {skip,Reason}
+%%
+%% TestCases = [TestCase | {sequence,SeqName}]
+%% TestCase = atom()
+%% Name of a test case.
+%% SeqName = atom()
+%% Name of a test case sequence.
+%% Reason = term()
+%% The reason for skipping all test cases.
+%%
+%% Description: Returns the list of test cases that are to be executed.
+%%--------------------------------------------------------------------
+all() ->
+ [tc1, tc2, tc3].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ {skip,"Skipped"}.
+
+tc3(_Config) ->
+ exit('Failing').
diff --git a/lib/common_test/test/ct_groups_test_1_SUITE.erl b/lib/common_test/test/ct_groups_test_1_SUITE.erl
new file mode 100644
index 0000000000..1761b773f5
--- /dev/null
+++ b/lib/common_test/test/ct_groups_test_1_SUITE.erl
@@ -0,0 +1,1226 @@
+%%
+%% %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_groups_test_1_SUITE
+%%%
+%%% Description:
+%%% Test some simple test case group scenarios.
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_groups_test_1_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) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+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).
+
+all(doc) ->
+ ["Run smoke tests of Common Test."];
+
+all(suite) ->
+ [groups_suite_1, groups_suite_2,
+ groups_suites_1, groups_dir_1, groups_dirs_1].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+
+groups_suite_1(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Suite = filename:join(DataDir, "groups_1/test/groups_11_SUITE"),
+
+ {Opts,ERPid} = setup({suite,Suite}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(groups_suite_1,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(groups_suite_1),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%%
+
+groups_suite_2(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Suite = filename:join(DataDir, "groups_1/test/groups_12_SUITE"),
+
+ {Opts,ERPid} = setup({suite,Suite}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(groups_suite_2,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(groups_suite_2),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%%
+
+groups_suites_1(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Suites = [filename:join(DataDir, "groups_1/test/groups_11_SUITE"),
+ filename:join(DataDir, "groups_1/test/groups_12_SUITE")],
+
+ {Opts,ERPid} = setup({suite,Suites}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(groups_suites_1,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(groups_suites_1),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%%
+
+groups_dir_1(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Dir = filename:join(DataDir, "groups_1"),
+
+ {Opts,ERPid} = setup({dir,Dir}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(groups_dir_1,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(groups_dir_1),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+groups_dirs_1(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Dirs = [filename:join(DataDir, "groups_1"),
+ filename:join(DataDir, "groups_2")],
+
+ {Opts,ERPid} = setup({dir,Dirs}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(groups_dirs_1,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(groups_dirs_1),
+ 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 ++ [Test,{event_handler,{?eh,EvHArgs}}],
+ 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
+%%%-----------------------------------------------------------------
+
+test_events(groups_suite_1) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,15}},
+ {?eh,tc_start,{groups_11_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_1a,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1a,[]},ok}}],
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_1b,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1b,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_2,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_2,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2a,ok}},
+ {?eh,test_stats,{7,0,{0,0}}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3a,ok}},
+ {?eh,test_stats,{8,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3b,ok}},
+ {?eh,test_stats,{9,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{10,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_2,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_2,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{11,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_4,[]},ok}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_5,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_5,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_5a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_5a,ok}},
+ {?eh,test_stats,{12,0,{0,0}}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_6,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_6,[]},ok}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_7,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_7,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_7a,ok}},
+ {?eh,test_stats,{13,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_7b,ok}},
+ {?eh,test_stats,{14,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_7,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_7,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_6,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_6,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{15,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_5,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_5,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_11_SUITE,end_per_suite,init}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(groups_suite_2) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,unknown}},
+ {?eh,tc_start,{groups_12_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_12_SUITE,init_per_suite,ok}},
+
+ {shuffle,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_1a,[{shuffle,'_'}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_1a,[{shuffle,'_'}]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1c}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1c,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_1a,[shuffle]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_1a,[shuffle]},ok}}]},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_1b,[parallel]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_1b,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_12_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{7,0,{0,0}}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_2,[parallel]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2a,ok}},
+
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_3,[{repeat,1}]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_3,[{repeat,1}]},ok}}],
+
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_3,[]},ok}}],
+
+ {?eh,tc_start,{groups_12_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{13,0,{0,0}}},
+
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_2,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_12_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{14,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_4,[]},ok}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_5,[parallel]},ok}},
+
+ %% the done event could come in during the parallel subgroup
+ %% and we can't test that, yet...
+ %% {?eh,tc_start,{groups_12_SUITE,testcase_5a}},
+ %% {?eh,tc_done,{groups_12_SUITE,testcase_5a,ok}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_6,[parallel]},ok}},
+
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_7,[sequence]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_7a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_7b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_7,[sequence]},ok}}],
+
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_6,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_12_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{18,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_5,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_12_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_12_SUITE,end_per_suite,init}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(groups_suites_1) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{2,2,unknown}},
+ {?eh,tc_start,{groups_11_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_1a,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1a,[]},ok}}],
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_1b,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1b,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_2,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_2,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2a,ok}},
+ {?eh,test_stats,{7,0,{0,0}}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3a,ok}},
+ {?eh,test_stats,{8,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3b,ok}},
+ {?eh,test_stats,{9,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{10,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_2,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_2,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{11,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_4,[]},ok}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_5,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_5,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_5a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_5a,ok}},
+ {?eh,test_stats,{12,0,{0,0}}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_6,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_6,[]},ok}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_7,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_7,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_7a,ok}},
+ {?eh,test_stats,{13,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_7b,ok}},
+ {?eh,test_stats,{14,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_7,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_7,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_6,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_6,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{15,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_5,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_5,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_11_SUITE,end_per_suite,init}},
+
+ {?eh,tc_start,{groups_12_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_12_SUITE,init_per_suite,ok}},
+
+ {shuffle,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_1a,[{shuffle,'_'}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_1a,[{shuffle,'_'}]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1c}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1c,ok}},
+ {?eh,test_stats,{16,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{17,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{18,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_1a,[shuffle]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_1a,[shuffle]},ok}}]},
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_1b,[parallel]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{20,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_1b,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{21,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{22,0,{0,0}}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_2,[parallel]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2a,ok}},
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_3,[{repeat,1}]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_3,[{repeat,1}]},ok}}],
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_12_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{28,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_2,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_12_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{29,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_4,[]},ok}},
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_5,[parallel]},ok}},
+
+ %% the done event could come in during the parallel subgroup
+ %% and we can't test that, yet...
+ %% {?eh,tc_start,{groups_12_SUITE,testcase_5a}},
+ %% {?eh,tc_done,{groups_12_SUITE,testcase_5a,ok}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_6,[parallel]},ok}},
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_7,[sequence]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_7a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_7b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_7,[sequence]},ok}}],
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_6,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{33,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_5,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_12_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_12_SUITE,end_per_suite,init}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(groups_dir_1) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,2,unknown}},
+ {?eh,tc_start,{groups_11_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_1a,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1a,[]},ok}}],
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_1b,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1b,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_2,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_2,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2a,ok}},
+ {?eh,test_stats,{7,0,{0,0}}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3a,ok}},
+ {?eh,test_stats,{8,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3b,ok}},
+ {?eh,test_stats,{9,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{10,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_2,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_2,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{11,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_4,[]},ok}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_5,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_5,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_5a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_5a,ok}},
+ {?eh,test_stats,{12,0,{0,0}}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_6,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_6,[]},ok}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_7,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_7,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_7a,ok}},
+ {?eh,test_stats,{13,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_7b,ok}},
+ {?eh,test_stats,{14,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_7,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_7,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_6,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_6,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{15,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_5,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_5,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_11_SUITE,end_per_suite,init}},
+
+ {?eh,tc_start,{groups_12_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_12_SUITE,init_per_suite,ok}},
+
+ {shuffle,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_1a,[{shuffle,'_'}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_1a,[{shuffle,'_'}]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{16,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1c}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1c,ok}},
+ {?eh,test_stats,{17,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{18,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_1a,[shuffle]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_1a,[shuffle]},ok}}]},
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_1b,[parallel]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{20,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_1b,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{21,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{22,0,{0,0}}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_2,[parallel]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2a,ok}},
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_3,[{repeat,1}]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_3,[{repeat,1}]},ok}}],
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_12_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{28,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_2,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_12_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{29,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_4,[]},ok}},
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_5,[parallel]},ok}},
+
+ %% the done event could come in during the parallel subgroup
+ %% and we can't test that, yet...
+ %% {?eh,tc_start,{groups_12_SUITE,testcase_5a}},
+ %% {?eh,tc_done,{groups_12_SUITE,testcase_5a,ok}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_6,[parallel]},ok}},
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_7,[sequence]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_7a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_7b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_7,[sequence]},ok}}],
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_6,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{33,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_5,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_12_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_12_SUITE,end_per_suite,init}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}];
+
+test_events(groups_dirs_1) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{2,4,unknown}},
+
+ {?eh,tc_start,{groups_11_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_1a,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1a,[]},ok}}],
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_1b,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_1b,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_2,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_2,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2a,ok}},
+ {?eh,test_stats,{7,0,{0,0}}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3a,ok}},
+ {?eh,test_stats,{8,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3b,ok}},
+ {?eh,test_stats,{9,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{10,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_2,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_2,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{11,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_4,[]},ok}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_5,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_5,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_5a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_5a,ok}},
+ {?eh,test_stats,{12,0,{0,0}}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_6,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_6,[]},ok}},
+ [{?eh,tc_start,{groups_11_SUITE,{init_per_group,test_group_7,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{init_per_group,test_group_7,[]},ok}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_7a,ok}},
+ {?eh,test_stats,{13,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_7b,ok}},
+ {?eh,test_stats,{14,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_7,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_7,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_6,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_6,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_11_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{15,0,{0,0}}},
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_5,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_5,[]},ok}}],
+ {?eh,tc_start,{groups_11_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_11_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_11_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_11_SUITE,end_per_suite,init}},
+
+ {?eh,tc_start,{groups_12_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_12_SUITE,init_per_suite,ok}},
+
+ {shuffle,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_1a,[{shuffle,'_'}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_1a,[{shuffle,'_'}]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{16,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1c}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1c,ok}},
+ {?eh,test_stats,{17,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{18,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_1a,[shuffle]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_1a,[shuffle]},ok}}]},
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_1b,[parallel]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{20,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_1b,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{21,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{22,0,{0,0}}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_2,[parallel]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2a,ok}},
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_3,[{repeat,1}]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_3,[{repeat,1}]},ok}}],
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_12_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{28,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_2,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_12_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{29,0,{0,0}}},
+
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_4,[]},ok}},
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_5,[parallel]},ok}},
+
+ %% the done event could come in during the parallel subgroup
+ %% and we can't test that, yet...
+ %% {?eh,tc_start,{groups_12_SUITE,testcase_5a}},
+ %% {?eh,tc_done,{groups_12_SUITE,testcase_5a,ok}},
+
+ {parallel,[{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_6,[parallel]},ok}},
+ [{?eh,tc_start,{groups_12_SUITE,{init_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,{groups_12_SUITE,{init_per_group,test_group_7,[sequence]},ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_7a,ok}},
+ {?eh,tc_start,{groups_12_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_7b,ok}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_7,[sequence]},ok}}],
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_6,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_12_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{33,0,{0,0}}},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_5,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_12_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,{groups_12_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_12_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_12_SUITE,end_per_suite,init}},
+
+ {?eh,tc_start,{groups_21_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{34,0,{0,0}}},
+
+ [{?eh,tc_start,
+ {groups_21_SUITE,{init_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{init_per_group,test_group_1a,[]},ok}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{35,0,{0,0}}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{36,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_21_SUITE,{end_per_group,test_group_1a,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{end_per_group,test_group_1a,[]},ok}}],
+
+ [{?eh,tc_start,
+ {groups_21_SUITE,{init_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{init_per_group,test_group_1b,[]},ok}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_1a,ok}},
+ {?eh,test_stats,{37,0,{0,0}}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{38,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_21_SUITE,{end_per_group,test_group_1b,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{end_per_group,test_group_1b,[]},ok}}],
+ {?eh,tc_start,{groups_21_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{39,0,{0,0}}},
+
+ [{?eh,tc_start,
+ {groups_21_SUITE,{init_per_group,test_group_2,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{init_per_group,test_group_2,[]},ok}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_2a,ok}},
+ {?eh,test_stats,{40,0,{0,0}}},
+ [{?eh,tc_start,
+ {groups_21_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_3a,ok}},
+ {?eh,test_stats,{41,0,{0,0}}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_3b,ok}},
+ {?eh,test_stats,{42,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_21_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_21_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{43,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_21_SUITE,{end_per_group,test_group_2,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{end_per_group,test_group_2,[]},ok}}],
+
+ {?eh,tc_start,{groups_21_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{44,0,{0,0}}},
+
+ [{?eh,tc_start,
+ {groups_21_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{init_per_group,test_group_4,[]},ok}},
+ [{?eh,tc_start,
+ {groups_21_SUITE,{init_per_group,test_group_5,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{init_per_group,test_group_5,[]},ok}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_5a}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_5a,ok}},
+ {?eh,test_stats,{45,0,{0,0}}},
+ [{?eh,tc_start,
+ {groups_21_SUITE,{init_per_group,test_group_6,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{init_per_group,test_group_6,[]},ok}},
+ [{?eh,tc_start,
+ {groups_21_SUITE,{init_per_group,test_group_7,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{init_per_group,test_group_7,[]},ok}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_7a,ok}},
+ {?eh,test_stats,{46,0,{0,0}}},
+ {?eh,tc_start,{groups_21_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_7b,ok}},
+ {?eh,test_stats,{47,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_21_SUITE,{end_per_group,test_group_7,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{end_per_group,test_group_7,[]},ok}}],
+ {?eh,tc_start,
+ {groups_21_SUITE,{end_per_group,test_group_6,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{end_per_group,test_group_6,[]},ok}}],
+ {?eh,tc_start,{groups_21_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_21_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{48,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_21_SUITE,{end_per_group,test_group_5,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{end_per_group,test_group_5,[]},ok}}],
+ {?eh,tc_start,
+ {groups_21_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,
+ {groups_21_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_21_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_21_SUITE,end_per_suite,init}},
+
+ {?eh,tc_start,{groups_22_SUITE,init_per_suite}},
+ {?eh,tc_done,{groups_22_SUITE,init_per_suite,ok}},
+
+ {shuffle,
+ [{?eh,tc_start,
+ {groups_22_SUITE,
+ {init_per_group,test_group_1a,[{shuffle,'_'}]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,
+ {init_per_group,test_group_1a,[{shuffle,'_'}]},
+ ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_1a,ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_1b,ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_1c}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_1c,ok}},
+ {?eh,test_stats,{51,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_1a,[shuffle]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_1a,[shuffle]},ok}}]},
+
+ {parallel,
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_1b,[parallel]},ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_1a}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_1a,ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_1b}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_1b,ok}},
+ {?eh,test_stats,{53,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_1b,[parallel]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_1b,[parallel]},ok}}]},
+
+ {?eh,tc_start,{groups_22_SUITE,testcase_1}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_1,ok}},
+ {?eh,test_stats,{54,0,{0,0}}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_2}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_2,ok}},
+ {?eh,test_stats,{55,0,{0,0}}},
+
+ {parallel,
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_2,[parallel]},ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_2a}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_2a,ok}},
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_3,[{repeat,1}]},ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_3,[{repeat,1}]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_3,[{repeat,1}]},ok}}],
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_3,[]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_3,[]},ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_3a}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_3a,ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_3b}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_3b,ok}},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_3,[]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_3,[]},ok}}],
+ {?eh,tc_start,{groups_22_SUITE,testcase_2b}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_2b,ok}},
+ {?eh,test_stats,{61,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_2,[parallel]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_2,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_22_SUITE,testcase_3}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_3,ok}},
+ {?eh,test_stats,{62,0,{0,0}}},
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_4,[]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_4,[]},ok}},
+
+ {parallel,
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_5,[parallel]},ok}},
+
+ %% the done event could come in during the parallel subgroup
+ %% and we can't test that, yet...
+ %% {?eh,tc_start,{groups_22_SUITE,testcase_5a}},
+ %% {?eh,tc_done,{groups_22_SUITE,testcase_5a,ok}},
+
+ {parallel,
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_6,[parallel]},ok}},
+ [{?eh,tc_start,
+ {groups_22_SUITE,{init_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{init_per_group,test_group_7,[sequence]},ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_7a}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_7a,ok}},
+ {?eh,tc_start,{groups_22_SUITE,testcase_7b}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_7b,ok}},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_7,[sequence]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_7,[sequence]},ok}}],
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_6,[parallel]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_6,[parallel]},ok}}]},
+ {?eh,tc_start,{groups_22_SUITE,testcase_5b}},
+ {?eh,tc_done,{groups_22_SUITE,testcase_5b,ok}},
+ {?eh,test_stats,{66,0,{0,0}}},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_5,[parallel]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_5,[parallel]},ok}}]},
+ {?eh,tc_start,
+ {groups_22_SUITE,{end_per_group,test_group_4,[]}}},
+ {?eh,tc_done,
+ {groups_22_SUITE,{end_per_group,test_group_4,[]},ok}}],
+
+ {?eh,tc_start,{groups_22_SUITE,end_per_suite}},
+ {?eh,tc_done,{groups_22_SUITE,end_per_suite,init}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}].
diff --git a/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_1/test/groups_11_SUITE.erl b/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_1/test/groups_11_SUITE.erl
new file mode 100644
index 0000000000..c6d50443d0
--- /dev/null
+++ b/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_1/test/groups_11_SUITE.erl
@@ -0,0 +1,280 @@
+%%
+%% %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%
+%%
+-module(groups_11_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%====================================================================
+%% COMMON TEST CALLBACK FUNCTIONS
+%%====================================================================
+
+suite() ->
+ [{timetrap,{minutes,1}}].
+
+groups() ->
+ [
+ {test_group_1a, [testcase_1a,testcase_1b]},
+
+ {test_group_1b, [], [testcase_1a,testcase_1b]},
+
+ {test_group_2, [], [testcase_2a,
+
+ {test_group_3, [], [testcase_3a,
+ testcase_3b]},
+ testcase_2b]},
+
+ {test_group_4, [{test_group_5, [], [testcase_5a,
+
+ {group, test_group_6},
+
+ testcase_5b]}]},
+
+ {test_group_6, [{group, test_group_7}]},
+
+ {test_group_7, [testcase_7a,testcase_7b]}
+ ].
+
+all() ->
+ [testcase_1,
+ {group, test_group_1a},
+ {group, test_group_1b},
+ testcase_2,
+ {group, test_group_2},
+ testcase_3,
+ {group, test_group_4}].
+
+%% this func only for internal test purposes
+grs_and_tcs() ->
+ {[
+ test_group_1a, test_group_1b,
+ test_group_2, test_group_3,
+ test_group_4, test_group_5,
+ test_group_6, test_group_7
+ ],
+ [
+ testcase_1,
+ testcase_1a, testcase_1b,
+ testcase_2,
+ testcase_2a, testcase_2b,
+ testcase_3a, testcase_3b,
+ testcase_3,
+ testcase_5a, testcase_5b,
+ testcase_7a, testcase_7b
+ ]}.
+
+%%--------------------------------------------------------------------
+%% Suite Configuration
+%%--------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ [{suite,init}|Config].
+
+end_per_suite(Config) ->
+ init = ?config(suite,Config).
+
+%%--------------------------------------------------------------------
+%% Group Configuration
+%%--------------------------------------------------------------------
+
+init_per_group(Group, Config) ->
+ [{name,Group}] = ?config(tc_group_properties,Config),
+ {Grs,_} = grs_and_tcs(),
+ case lists:member(Group, Grs) of
+ true ->
+ init = ?config(suite,Config),
+ [{Group,Group} | Config];
+ false ->
+ ct:fail({bad_group,Group})
+ end.
+
+end_per_group(Group, Config) ->
+ {Grs,_} = grs_and_tcs(),
+ case lists:member(Group, Grs) of
+ true ->
+ init = ?config(suite,Config),
+ Group = ?config(Group,Config),
+ ok;
+ false ->
+ ct:fail({bad_group,Group})
+ end.
+
+%%--------------------------------------------------------------------
+%% Testcase Configuration
+%%--------------------------------------------------------------------
+
+init_per_testcase(TestCase, Config) ->
+ {_,TCs} = grs_and_tcs(),
+ case lists:member(TestCase, TCs) of
+ true ->
+ init = ?config(suite,Config),
+ [{TestCase,TestCase} | Config];
+ false ->
+ ct:fail({unknown_testcase,TestCase})
+ end.
+
+end_per_testcase(TestCase, Config) ->
+ {_,TCs} = grs_and_tcs(),
+ case lists:member(TestCase, TCs) of
+ true ->
+ init = ?config(suite,Config),
+ TestCase = ?config(TestCase,Config),
+ ok;
+ false ->
+ ct:fail({unknown_testcase,TestCase})
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Testcases
+%%--------------------------------------------------------------------
+
+testcase_1() ->
+ [].
+testcase_1(Config) ->
+ init = ?config(suite,Config),
+ testcase_1 = ?config(testcase_1,Config),
+ ok.
+
+testcase_1a() ->
+ [].
+testcase_1a(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ testcase_1a = ?config(testcase_1a,Config),
+ ok.
+testcase_1b() ->
+ [].
+testcase_1b(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ undefined = ?config(testcase_1a,Config),
+ testcase_1b = ?config(testcase_1b,Config),
+ ok.
+
+testcase_2() ->
+ [].
+testcase_2(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_1a,Config),
+ undefined = ?config(test_group_1b,Config),
+ testcase_2 = ?config(testcase_2,Config),
+ ok.
+
+testcase_2a() ->
+ [].
+testcase_2a(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ testcase_2a = ?config(testcase_2a,Config),
+ ok.
+testcase_2b() ->
+ [].
+testcase_2b(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ undefined = ?config(testcase_2a,Config),
+ testcase_2b = ?config(testcase_2b,Config),
+ ok.
+
+testcase_3a() ->
+ [].
+testcase_3a(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ test_group_3 = ?config(test_group_3,Config),
+ undefined = ?config(testcase_2b,Config),
+ testcase_3a = ?config(testcase_3a,Config),
+ ok.
+testcase_3b() ->
+ [].
+testcase_3b(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ test_group_3 = ?config(test_group_3,Config),
+ undefined = ?config(testcase_3a,Config),
+ testcase_3b = ?config(testcase_3b,Config),
+ ok.
+
+testcase_3() ->
+ [].
+testcase_3(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_2,Config),
+ undefined = ?config(test_group_3,Config),
+ testcase_3 = ?config(testcase_3,Config),
+ ok.
+
+testcase_5a() ->
+ [].
+testcase_5a(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_3,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ undefined = ?config(testcase_3,Config),
+ testcase_5a = ?config(testcase_5a,Config),
+ ok.
+testcase_5b() ->
+ [].
+testcase_5b(Config) ->
+ init = ?config(suite,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ undefined = ?config(testcase_5a,Config),
+ testcase_5b = ?config(testcase_5b,Config),
+ ok.
+
+testcase_7a() ->
+ [].
+testcase_7a(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_3,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ test_group_6 = ?config(test_group_6,Config),
+ test_group_7 = ?config(test_group_7,Config),
+ testcase_7a = ?config(testcase_7a,Config),
+ ok.
+testcase_7b() ->
+ [].
+testcase_7b(Config) ->
+ init = ?config(suite,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ test_group_6 = ?config(test_group_6,Config),
+ test_group_7 = ?config(test_group_7,Config),
+ undefined = ?config(testcase_7a,Config),
+ testcase_7b = ?config(testcase_7b,Config),
+ ok.
diff --git a/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_1/test/groups_12_SUITE.erl b/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_1/test/groups_12_SUITE.erl
new file mode 100644
index 0000000000..b261ef581f
--- /dev/null
+++ b/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_1/test/groups_12_SUITE.erl
@@ -0,0 +1,310 @@
+%%
+%% %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%
+%%
+-module(groups_12_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%====================================================================
+%% COMMON TEST CALLBACK FUNCTIONS
+%%====================================================================
+
+suite() ->
+ [{timetrap,{minutes,1}}].
+
+groups() ->
+ [
+ {test_group_1a, [shuffle], [testcase_1a,testcase_1b,testcase_1c]},
+
+ {test_group_1b, [parallel], [testcase_1a,testcase_1b]},
+
+ {test_group_2, [parallel], [testcase_2a,
+
+ {test_group_3, [{repeat,1}],
+ [testcase_3a, testcase_3b]},
+
+ testcase_2b]},
+
+ {test_group_4, [{test_group_5, [parallel], [testcase_5a,
+
+ {group, test_group_6},
+
+ testcase_5b]}]},
+
+ {test_group_6, [parallel], [{group, test_group_7}]},
+
+ {test_group_7, [sequence], [testcase_7a,testcase_7b]}
+ ].
+
+all() ->
+ [{group, test_group_1a},
+ {group, test_group_1b},
+ testcase_1,
+ testcase_2,
+ {group, test_group_2},
+ testcase_3,
+ {group, test_group_4}].
+
+%% this func only for internal test purposes
+grs_and_tcs() ->
+ {[
+ test_group_1a, test_group_1b,
+ test_group_2, test_group_3,
+ test_group_4, test_group_5,
+ test_group_6, test_group_7
+ ],
+ [
+ testcase_1a, testcase_1b, testcase_1c,
+ testcase_1,
+ testcase_2,
+ testcase_2a, testcase_2b,
+ testcase_3a, testcase_3b,
+ testcase_3,
+ testcase_5a, testcase_5b,
+ testcase_7a, testcase_7b
+ ]}.
+
+%%--------------------------------------------------------------------
+%% Suite Configuration
+%%--------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ [{suite,init}|Config].
+
+end_per_suite(Config) ->
+ init = ?config(suite,Config).
+
+%%--------------------------------------------------------------------
+%% Group Configuration
+%%--------------------------------------------------------------------
+
+init_per_group(Group, Config) ->
+ Cmt =
+ case {Group,?config(tc_group_properties,Config)} of
+ {test_group_1a,[{shuffle,S},{name,test_group_1a}]} ->
+ io_lib:format("shuffled, ~w", [S]);
+ {test_group_1b,[{name,test_group_1b},parallel]} -> "parallel";
+ {test_group_2,[{name,test_group_2},parallel]} -> "parallel";
+ {test_group_3,[{name,test_group_3},{repeat,1}]} -> "repeat 1";
+ {test_group_3,[{name,test_group_3}]} -> "repeat 0";
+ {test_group_4,[{name,test_group_4}]} -> ok;
+ {test_group_5,[{name,test_group_5},parallel]} -> "parallel";
+ {test_group_6,[{name,test_group_6},parallel]} -> "parallel";
+ {test_group_7,[{name,test_group_7},sequence]} -> "sequence"
+ end,
+ {Grs,_} = grs_and_tcs(),
+ case lists:member(Group, Grs) of
+ true ->
+ init = ?config(suite,Config),
+ ct:comment(io_lib:format("~w, ~s", [Group,Cmt])),
+ [{Group,Group} | Config];
+ false ->
+ ct:fail({bad_group,Group})
+ end.
+
+end_per_group(Group, Config) ->
+ {Grs,_} = grs_and_tcs(),
+ case lists:member(Group, Grs) of
+ true ->
+ init = ?config(suite,Config),
+ Group = ?config(Group,Config),
+ ok;
+ false ->
+ ct:fail({bad_group,Group})
+ end.
+
+%%--------------------------------------------------------------------
+%% Testcase Configuration
+%%--------------------------------------------------------------------
+
+init_per_testcase(TestCase, Config) ->
+ {_,TCs} = grs_and_tcs(),
+ case lists:member(TestCase, TCs) of
+ true ->
+ init = ?config(suite,Config),
+ [{TestCase,TestCase} | Config];
+ false ->
+ ct:fail({unknown_testcase,TestCase})
+ end.
+
+end_per_testcase(TestCase, Config) ->
+ {_,TCs} = grs_and_tcs(),
+ case lists:member(TestCase, TCs) of
+ true ->
+ init = ?config(suite,Config),
+ TestCase = ?config(TestCase,Config),
+ ok;
+ false ->
+ ct:fail({unknown_testcase,TestCase})
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Testcases
+%%--------------------------------------------------------------------
+
+testcase_1a() ->
+ [].
+testcase_1a(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ testcase_1a = ?config(testcase_1a,Config),
+ ok.
+testcase_1b() ->
+ [].
+testcase_1b(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ undefined = ?config(testcase_1a,Config),
+ testcase_1b = ?config(testcase_1b,Config),
+ ok.
+
+testcase_1c() ->
+ [].
+testcase_1c(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ undefined = ?config(testcase_1b,Config),
+ testcase_1c = ?config(testcase_1c,Config),
+ ok.
+
+testcase_1() ->
+ [].
+testcase_1(Config) ->
+ init = ?config(suite,Config),
+ testcase_1 = ?config(testcase_1,Config),
+ ok.
+
+testcase_2() ->
+ [].
+testcase_2(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_1a,Config),
+ undefined = ?config(test_group_1b,Config),
+ testcase_2 = ?config(testcase_2,Config),
+ ok.
+
+testcase_2a() ->
+ [].
+testcase_2a(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ testcase_2a = ?config(testcase_2a,Config),
+ ok.
+testcase_2b() ->
+ [].
+testcase_2b(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ undefined = ?config(testcase_2a,Config),
+ testcase_2b = ?config(testcase_2b,Config),
+ ok.
+
+testcase_3a() ->
+ [].
+testcase_3a(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ test_group_3 = ?config(test_group_3,Config),
+ undefined = ?config(testcase_2b,Config),
+ testcase_3a = ?config(testcase_3a,Config),
+ ok.
+testcase_3b() ->
+ [].
+testcase_3b(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ test_group_3 = ?config(test_group_3,Config),
+ undefined = ?config(testcase_3a,Config),
+ testcase_3b = ?config(testcase_3b,Config),
+ ok.
+
+testcase_3() ->
+ [].
+testcase_3(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_2,Config),
+ undefined = ?config(test_group_3,Config),
+ testcase_3 = ?config(testcase_3,Config),
+ ok.
+
+testcase_5a() ->
+ [].
+testcase_5a(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_3,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ undefined = ?config(testcase_3,Config),
+ testcase_5a = ?config(testcase_5a,Config),
+ ok.
+testcase_5b() ->
+ [].
+testcase_5b(Config) ->
+ init = ?config(suite,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ undefined = ?config(testcase_5a,Config),
+ testcase_5b = ?config(testcase_5b,Config),
+ ok.
+
+testcase_7a() ->
+ [].
+testcase_7a(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_3,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ test_group_6 = ?config(test_group_6,Config),
+ test_group_7 = ?config(test_group_7,Config),
+ testcase_7a = ?config(testcase_7a,Config),
+ ok.
+testcase_7b() ->
+ [].
+testcase_7b(Config) ->
+ init = ?config(suite,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ test_group_6 = ?config(test_group_6,Config),
+ test_group_7 = ?config(test_group_7,Config),
+ undefined = ?config(testcase_7a,Config),
+ testcase_7b = ?config(testcase_7b,Config),
+ ok.
diff --git a/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_2/test/groups_21_SUITE.erl b/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_2/test/groups_21_SUITE.erl
new file mode 100644
index 0000000000..42b10d1803
--- /dev/null
+++ b/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_2/test/groups_21_SUITE.erl
@@ -0,0 +1,280 @@
+%%
+%% %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%
+%%
+-module(groups_21_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%====================================================================
+%% COMMON TEST CALLBACK FUNCTIONS
+%%====================================================================
+
+suite() ->
+ [{timetrap,{minutes,1}}].
+
+groups() ->
+ [
+ {test_group_1a, [testcase_1a,testcase_1b]},
+
+ {test_group_1b, [], [testcase_1a,testcase_1b]},
+
+ {test_group_2, [], [testcase_2a,
+
+ {test_group_3, [], [testcase_3a,
+ testcase_3b]},
+ testcase_2b]},
+
+ {test_group_4, [{test_group_5, [], [testcase_5a,
+
+ {group, test_group_6},
+
+ testcase_5b]}]},
+
+ {test_group_6, [{group, test_group_7}]},
+
+ {test_group_7, [testcase_7a,testcase_7b]}
+ ].
+
+all() ->
+ [testcase_1,
+ {group, test_group_1a},
+ {group, test_group_1b},
+ testcase_2,
+ {group, test_group_2},
+ testcase_3,
+ {group, test_group_4}].
+
+%% this func only for internal test purposes
+grs_and_tcs() ->
+ {[
+ test_group_1a, test_group_1b,
+ test_group_2, test_group_3,
+ test_group_4, test_group_5,
+ test_group_6, test_group_7
+ ],
+ [
+ testcase_1,
+ testcase_1a, testcase_1b,
+ testcase_2,
+ testcase_2a, testcase_2b,
+ testcase_3a, testcase_3b,
+ testcase_3,
+ testcase_5a, testcase_5b,
+ testcase_7a, testcase_7b
+ ]}.
+
+%%--------------------------------------------------------------------
+%% Suite Configuration
+%%--------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ [{suite,init}|Config].
+
+end_per_suite(Config) ->
+ init = ?config(suite,Config).
+
+%%--------------------------------------------------------------------
+%% Group Configuration
+%%--------------------------------------------------------------------
+
+init_per_group(Group, Config) ->
+ [{name,Group}] = ?config(tc_group_properties,Config),
+ {Grs,_} = grs_and_tcs(),
+ case lists:member(Group, Grs) of
+ true ->
+ init = ?config(suite,Config),
+ [{Group,Group} | Config];
+ false ->
+ ct:fail({bad_group,Group})
+ end.
+
+end_per_group(Group, Config) ->
+ {Grs,_} = grs_and_tcs(),
+ case lists:member(Group, Grs) of
+ true ->
+ init = ?config(suite,Config),
+ Group = ?config(Group,Config),
+ ok;
+ false ->
+ ct:fail({bad_group,Group})
+ end.
+
+%%--------------------------------------------------------------------
+%% Testcase Configuration
+%%--------------------------------------------------------------------
+
+init_per_testcase(TestCase, Config) ->
+ {_,TCs} = grs_and_tcs(),
+ case lists:member(TestCase, TCs) of
+ true ->
+ init = ?config(suite,Config),
+ [{TestCase,TestCase} | Config];
+ false ->
+ ct:fail({unknown_testcase,TestCase})
+ end.
+
+end_per_testcase(TestCase, Config) ->
+ {_,TCs} = grs_and_tcs(),
+ case lists:member(TestCase, TCs) of
+ true ->
+ init = ?config(suite,Config),
+ TestCase = ?config(TestCase,Config),
+ ok;
+ false ->
+ ct:fail({unknown_testcase,TestCase})
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Testcases
+%%--------------------------------------------------------------------
+
+testcase_1() ->
+ [].
+testcase_1(Config) ->
+ init = ?config(suite,Config),
+ testcase_1 = ?config(testcase_1,Config),
+ ok.
+
+testcase_1a() ->
+ [].
+testcase_1a(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ testcase_1a = ?config(testcase_1a,Config),
+ ok.
+testcase_1b() ->
+ [].
+testcase_1b(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ undefined = ?config(testcase_1a,Config),
+ testcase_1b = ?config(testcase_1b,Config),
+ ok.
+
+testcase_2() ->
+ [].
+testcase_2(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_1a,Config),
+ undefined = ?config(test_group_1b,Config),
+ testcase_2 = ?config(testcase_2,Config),
+ ok.
+
+testcase_2a() ->
+ [].
+testcase_2a(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ testcase_2a = ?config(testcase_2a,Config),
+ ok.
+testcase_2b() ->
+ [].
+testcase_2b(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ undefined = ?config(testcase_2a,Config),
+ testcase_2b = ?config(testcase_2b,Config),
+ ok.
+
+testcase_3a() ->
+ [].
+testcase_3a(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ test_group_3 = ?config(test_group_3,Config),
+ undefined = ?config(testcase_2b,Config),
+ testcase_3a = ?config(testcase_3a,Config),
+ ok.
+testcase_3b() ->
+ [].
+testcase_3b(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ test_group_3 = ?config(test_group_3,Config),
+ undefined = ?config(testcase_3a,Config),
+ testcase_3b = ?config(testcase_3b,Config),
+ ok.
+
+testcase_3() ->
+ [].
+testcase_3(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_2,Config),
+ undefined = ?config(test_group_3,Config),
+ testcase_3 = ?config(testcase_3,Config),
+ ok.
+
+testcase_5a() ->
+ [].
+testcase_5a(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_3,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ undefined = ?config(testcase_3,Config),
+ testcase_5a = ?config(testcase_5a,Config),
+ ok.
+testcase_5b() ->
+ [].
+testcase_5b(Config) ->
+ init = ?config(suite,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ undefined = ?config(testcase_5a,Config),
+ testcase_5b = ?config(testcase_5b,Config),
+ ok.
+
+testcase_7a() ->
+ [].
+testcase_7a(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_3,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ test_group_6 = ?config(test_group_6,Config),
+ test_group_7 = ?config(test_group_7,Config),
+ testcase_7a = ?config(testcase_7a,Config),
+ ok.
+testcase_7b() ->
+ [].
+testcase_7b(Config) ->
+ init = ?config(suite,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ test_group_6 = ?config(test_group_6,Config),
+ test_group_7 = ?config(test_group_7,Config),
+ undefined = ?config(testcase_7a,Config),
+ testcase_7b = ?config(testcase_7b,Config),
+ ok.
diff --git a/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_2/test/groups_22_SUITE.erl b/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_2/test/groups_22_SUITE.erl
new file mode 100644
index 0000000000..2e19cf6310
--- /dev/null
+++ b/lib/common_test/test/ct_groups_test_1_SUITE_data/groups_2/test/groups_22_SUITE.erl
@@ -0,0 +1,310 @@
+%%
+%% %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%
+%%
+-module(groups_22_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%====================================================================
+%% COMMON TEST CALLBACK FUNCTIONS
+%%====================================================================
+
+suite() ->
+ [{timetrap,{minutes,1}}].
+
+groups() ->
+ [
+ {test_group_1a, [shuffle], [testcase_1a,testcase_1b,testcase_1c]},
+
+ {test_group_1b, [parallel], [testcase_1a,testcase_1b]},
+
+ {test_group_2, [parallel], [testcase_2a,
+
+ {test_group_3, [{repeat,1}],
+ [testcase_3a, testcase_3b]},
+
+ testcase_2b]},
+
+ {test_group_4, [{test_group_5, [parallel], [testcase_5a,
+
+ {group, test_group_6},
+
+ testcase_5b]}]},
+
+ {test_group_6, [parallel], [{group, test_group_7}]},
+
+ {test_group_7, [sequence], [testcase_7a,testcase_7b]}
+ ].
+
+all() ->
+ [{group, test_group_1a},
+ {group, test_group_1b},
+ testcase_1,
+ testcase_2,
+ {group, test_group_2},
+ testcase_3,
+ {group, test_group_4}].
+
+%% this func only for internal test purposes
+grs_and_tcs() ->
+ {[
+ test_group_1a, test_group_1b,
+ test_group_2, test_group_3,
+ test_group_4, test_group_5,
+ test_group_6, test_group_7
+ ],
+ [
+ testcase_1a, testcase_1b, testcase_1c,
+ testcase_1,
+ testcase_2,
+ testcase_2a, testcase_2b,
+ testcase_3a, testcase_3b,
+ testcase_3,
+ testcase_5a, testcase_5b,
+ testcase_7a, testcase_7b
+ ]}.
+
+%%--------------------------------------------------------------------
+%% Suite Configuration
+%%--------------------------------------------------------------------
+
+init_per_suite(Config) ->
+ [{suite,init}|Config].
+
+end_per_suite(Config) ->
+ init = ?config(suite,Config).
+
+%%--------------------------------------------------------------------
+%% Group Configuration
+%%--------------------------------------------------------------------
+
+init_per_group(Group, Config) ->
+ Cmt =
+ case {Group,?config(tc_group_properties,Config)} of
+ {test_group_1a,[{shuffle,S},{name,test_group_1a}]} ->
+ io_lib:format("shuffled, ~w", [S]);
+ {test_group_1b,[{name,test_group_1b},parallel]} -> "parallel";
+ {test_group_2,[{name,test_group_2},parallel]} -> "parallel";
+ {test_group_3,[{name,test_group_3},{repeat,1}]} -> "repeat 1";
+ {test_group_3,[{name,test_group_3}]} -> "repeat 0";
+ {test_group_4,[{name,test_group_4}]} -> ok;
+ {test_group_5,[{name,test_group_5},parallel]} -> "parallel";
+ {test_group_6,[{name,test_group_6},parallel]} -> "parallel";
+ {test_group_7,[{name,test_group_7},sequence]} -> "sequence"
+ end,
+ {Grs,_} = grs_and_tcs(),
+ case lists:member(Group, Grs) of
+ true ->
+ init = ?config(suite,Config),
+ ct:comment(io_lib:format("~w, ~s", [Group,Cmt])),
+ [{Group,Group} | Config];
+ false ->
+ ct:fail({bad_group,Group})
+ end.
+
+end_per_group(Group, Config) ->
+ {Grs,_} = grs_and_tcs(),
+ case lists:member(Group, Grs) of
+ true ->
+ init = ?config(suite,Config),
+ Group = ?config(Group,Config),
+ ok;
+ false ->
+ ct:fail({bad_group,Group})
+ end.
+
+%%--------------------------------------------------------------------
+%% Testcase Configuration
+%%--------------------------------------------------------------------
+
+init_per_testcase(TestCase, Config) ->
+ {_,TCs} = grs_and_tcs(),
+ case lists:member(TestCase, TCs) of
+ true ->
+ init = ?config(suite,Config),
+ [{TestCase,TestCase} | Config];
+ false ->
+ ct:fail({unknown_testcase,TestCase})
+ end.
+
+end_per_testcase(TestCase, Config) ->
+ {_,TCs} = grs_and_tcs(),
+ case lists:member(TestCase, TCs) of
+ true ->
+ init = ?config(suite,Config),
+ TestCase = ?config(TestCase,Config),
+ ok;
+ false ->
+ ct:fail({unknown_testcase,TestCase})
+ end.
+
+
+%%--------------------------------------------------------------------
+%% Testcases
+%%--------------------------------------------------------------------
+
+testcase_1a() ->
+ [].
+testcase_1a(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ testcase_1a = ?config(testcase_1a,Config),
+ ok.
+testcase_1b() ->
+ [].
+testcase_1b(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ undefined = ?config(testcase_1a,Config),
+ testcase_1b = ?config(testcase_1b,Config),
+ ok.
+
+testcase_1c() ->
+ [].
+testcase_1c(Config) ->
+ init = ?config(suite,Config),
+ case ?config(test_group_1a,Config) of
+ test_group_1a -> ok;
+ _ ->
+ case ?config(test_group_1b,Config) of
+ test_group_1b -> ok;
+ _ -> ct:fail(no_group_data)
+ end
+ end,
+ undefined = ?config(testcase_1b,Config),
+ testcase_1c = ?config(testcase_1c,Config),
+ ok.
+
+testcase_1() ->
+ [].
+testcase_1(Config) ->
+ init = ?config(suite,Config),
+ testcase_1 = ?config(testcase_1,Config),
+ ok.
+
+testcase_2() ->
+ [].
+testcase_2(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_1a,Config),
+ undefined = ?config(test_group_1b,Config),
+ testcase_2 = ?config(testcase_2,Config),
+ ok.
+
+testcase_2a() ->
+ [].
+testcase_2a(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ testcase_2a = ?config(testcase_2a,Config),
+ ok.
+testcase_2b() ->
+ [].
+testcase_2b(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ undefined = ?config(testcase_2a,Config),
+ testcase_2b = ?config(testcase_2b,Config),
+ ok.
+
+testcase_3a() ->
+ [].
+testcase_3a(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ test_group_3 = ?config(test_group_3,Config),
+ undefined = ?config(testcase_2b,Config),
+ testcase_3a = ?config(testcase_3a,Config),
+ ok.
+testcase_3b() ->
+ [].
+testcase_3b(Config) ->
+ init = ?config(suite,Config),
+ test_group_2 = ?config(test_group_2,Config),
+ test_group_3 = ?config(test_group_3,Config),
+ undefined = ?config(testcase_3a,Config),
+ testcase_3b = ?config(testcase_3b,Config),
+ ok.
+
+testcase_3() ->
+ [].
+testcase_3(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_2,Config),
+ undefined = ?config(test_group_3,Config),
+ testcase_3 = ?config(testcase_3,Config),
+ ok.
+
+testcase_5a() ->
+ [].
+testcase_5a(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_3,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ undefined = ?config(testcase_3,Config),
+ testcase_5a = ?config(testcase_5a,Config),
+ ok.
+testcase_5b() ->
+ [].
+testcase_5b(Config) ->
+ init = ?config(suite,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ undefined = ?config(testcase_5a,Config),
+ testcase_5b = ?config(testcase_5b,Config),
+ ok.
+
+testcase_7a() ->
+ [].
+testcase_7a(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(test_group_3,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ test_group_6 = ?config(test_group_6,Config),
+ test_group_7 = ?config(test_group_7,Config),
+ testcase_7a = ?config(testcase_7a,Config),
+ ok.
+testcase_7b() ->
+ [].
+testcase_7b(Config) ->
+ init = ?config(suite,Config),
+ test_group_4 = ?config(test_group_4,Config),
+ test_group_5 = ?config(test_group_5,Config),
+ test_group_6 = ?config(test_group_6,Config),
+ test_group_7 = ?config(test_group_7,Config),
+ undefined = ?config(testcase_7a,Config),
+ testcase_7b = ?config(testcase_7b,Config),
+ ok.
diff --git a/lib/common_test/test/ct_groups_test_2_SUITE.erl b/lib/common_test/test/ct_groups_test_2_SUITE.erl
new file mode 100644
index 0000000000..5a60d855b7
--- /dev/null
+++ b/lib/common_test/test/ct_groups_test_2_SUITE.erl
@@ -0,0 +1,110 @@
+%%
+%% %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_groups_test_2_SUITE
+%%%
+%%% Description:
+%%% Test some simple test case group scenarios.
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_groups_test_2_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) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+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).
+
+all(doc) ->
+ ["Run smoke tests of Common Test."];
+
+all(suite) ->
+ [missing_conf].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+
+missing_conf(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Suite = filename:join(DataDir, "groups_1/missing_conf_SUITE"),
+
+ {Opts,ERPid} = setup({suite,Suite}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(missing_conf_SUITE,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(missing_conf),
+ 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 ++ [Test,{event_handler,{?eh,EvHArgs}}],
+ 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
+%%%-----------------------------------------------------------------
+
+test_events(missing_conf) ->
+ exit(must_handle_this).
diff --git a/lib/common_test/test/ct_groups_test_2_SUITE_data/groups_1/missing_conf_SUITE.erl b/lib/common_test/test/ct_groups_test_2_SUITE_data/groups_1/missing_conf_SUITE.erl
new file mode 100644
index 0000000000..e7f48daaee
--- /dev/null
+++ b/lib/common_test/test/ct_groups_test_2_SUITE_data/groups_1/missing_conf_SUITE.erl
@@ -0,0 +1,62 @@
+%%
+%% %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%
+%%
+-module(missing_conf_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{group1,[],[tc1,tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [{group,group1}].
+
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE.erl b/lib/common_test/test/ct_skip_SUITE.erl
new file mode 100644
index 0000000000..9f428723f5
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE.erl
@@ -0,0 +1,565 @@
+%%
+%% %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_skip_SUITE
+%%%
+%%% Description:
+%%% Test auto- and user-skip functionality
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_skip_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) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+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).
+
+all(doc) ->
+ [""];
+
+all(suite) ->
+ [
+ auto_skip,
+ user_skip
+ ].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+auto_skip(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "skip/test/"++S) end,
+ Suites = [Join(DataDir, "auto_skip_1_SUITE"),
+ Join(DataDir, "auto_skip_2_SUITE"),
+ Join(DataDir, "auto_skip_3_SUITE"),
+ Join(DataDir, "auto_skip_4_SUITE"),
+ Join(DataDir, "auto_skip_5_SUITE"),
+ Join(DataDir, "auto_skip_6_SUITE"),
+ Join(DataDir, "auto_skip_7_SUITE"),
+ Join(DataDir, "auto_skip_8_SUITE"),
+ Join(DataDir, "auto_skip_9_SUITE"),
+ Join(DataDir, "auto_skip_10_SUITE"),
+ Join(DataDir, "auto_skip_11_SUITE")
+ ],
+
+ {Opts,ERPid} = setup({suite,Suites}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(auto_skip,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(auto_skip),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%%
+user_skip(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "skip/test/"++S) end,
+ Suites = [Join(DataDir, "user_skip_1_SUITE"),
+ Join(DataDir, "user_skip_2_SUITE"),
+ Join(DataDir, "user_skip_3_SUITE"),
+ Join(DataDir, "user_skip_4_SUITE"),
+ Join(DataDir, "user_skip_5_SUITE")],
+
+ {Opts,ERPid} = setup({suite,Suites}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(user_skip,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(user_skip),
+ 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 ++ [Test,{event_handler,{?eh,EvHArgs}}],
+ 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
+%%%-----------------------------------------------------------------
+test_events(auto_skip) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{11,11,34}},
+
+ {?eh,tc_start,{auto_skip_1_SUITE,init_per_suite}},
+ {?eh,tc_done,
+ {auto_skip_1_SUITE,init_per_suite,{failed,{error,init_per_suite_failed}}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_1_SUITE,tc1,{failed,{auto_skip_1_SUITE,init_per_suite,
+ {'EXIT',init_per_suite_failed}}}}},
+ {?eh,test_stats,{0,0,{0,1}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_1_SUITE,tc2,{failed,{auto_skip_1_SUITE,init_per_suite,
+ {'EXIT',init_per_suite_failed}}}}},
+ {?eh,test_stats,{0,0,{0,2}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_1_SUITE,end_per_suite,{failed,{auto_skip_1_SUITE,init_per_suite,
+ {'EXIT',init_per_suite_failed}}}}},
+
+ {?eh,tc_start,{auto_skip_2_SUITE,init_per_suite}},
+ {?eh,tc_done,
+ {auto_skip_2_SUITE,init_per_suite,{failed,{error,init_per_suite_failed}}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_2_SUITE,tc1,{failed,{auto_skip_2_SUITE,init_per_suite,
+ {'EXIT',init_per_suite_failed}}}}},
+ {?eh,test_stats,{0,0,{0,3}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_2_SUITE,end_per_suite,{failed,{auto_skip_2_SUITE,init_per_suite,
+ {'EXIT',init_per_suite_failed}}}}},
+
+ {?eh,tc_start,{auto_skip_3_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_3_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{auto_skip_3_SUITE,tc1}},
+ {?eh,tc_done,
+ {auto_skip_3_SUITE,tc1,
+ {skipped,{failed,{auto_skip_3_SUITE,init_per_testcase,
+ {init_per_testcase,tc1,failed}}}}}},
+ {?eh,test_stats,{0,0,{0,4}}},
+ {?eh,tc_start,{auto_skip_3_SUITE,tc2}},
+ {?eh,tc_done,{auto_skip_3_SUITE,tc2,ok}},
+ {?eh,test_stats,{1,0,{0,4}}},
+ {?eh,tc_start,{auto_skip_3_SUITE,end_per_suite}},
+ {?eh,tc_done,{auto_skip_3_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{auto_skip_4_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_4_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{auto_skip_4_SUITE,tc1}},
+ {?eh,tc_done,{auto_skip_4_SUITE,tc1,
+ {skipped,{failed,{auto_skip_4_SUITE,init_per_testcase,
+ {timetrap_timeout,1000}}}}}},
+ {?eh,test_stats,{1,0,{0,5}}},
+ {?eh,tc_start,{auto_skip_4_SUITE,tc2}},
+ {?eh,tc_done,{auto_skip_4_SUITE,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,5}}},
+ {?eh,tc_start,{auto_skip_4_SUITE,end_per_suite}},
+ {?eh,tc_done,{auto_skip_4_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{auto_skip_5_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_5_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{auto_skip_5_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,
+ {auto_skip_5_SUITE,{init_per_group,g1,[]},{failed,{error,{group,g1,failed}}}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_5_SUITE,tc1,{failed,{auto_skip_5_SUITE,init_per_group,
+ {'EXIT',{group,g1,failed}}}}}},
+ {?eh,test_stats,{2,0,{0,6}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_5_SUITE,tc2,{failed,{auto_skip_5_SUITE,init_per_group,
+ {'EXIT',{group,g1,failed}}}}}},
+ {?eh,test_stats,{2,0,{0,7}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_5_SUITE,end_per_group,{failed,{auto_skip_5_SUITE,init_per_group,
+ {'EXIT',{group,g1,failed}}}}}}],
+
+ {?eh,tc_start,{auto_skip_5_SUITE,end_per_suite}},
+ {?eh,tc_done,{auto_skip_5_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{auto_skip_6_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_6_SUITE,init_per_suite,ok}},
+ [{?eh,tc_start,{auto_skip_6_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,
+ {auto_skip_6_SUITE,{init_per_group,g1,[]},{failed,{error,{group,g1,failed}}}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_6_SUITE,tc1,{failed,{auto_skip_6_SUITE,init_per_group,
+ {'EXIT',{group,g1,failed}}}}}},
+ {?eh,test_stats,{2,0,{0,8}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_6_SUITE,tc3,{failed,{auto_skip_6_SUITE,init_per_group,
+ {'EXIT',{group,g1,failed}}}}}},
+ {?eh,test_stats,{2,0,{0,9}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_6_SUITE,tc4,{failed,{auto_skip_6_SUITE,init_per_group,
+ {'EXIT',{group,g1,failed}}}}}},
+ {?eh,test_stats,{2,0,{0,10}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_6_SUITE,tc2,{failed,{auto_skip_6_SUITE,init_per_group,
+ {'EXIT',{group,g1,failed}}}}}},
+ {?eh,test_stats,{2,0,{0,11}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_6_SUITE,end_per_group,{failed,{auto_skip_6_SUITE,init_per_group,
+ {'EXIT',{group,g1,failed}}}}}}],
+
+ [{?eh,tc_start,{auto_skip_6_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{auto_skip_6_SUITE,{init_per_group,g3,[]},ok}},
+ {?eh,tc_start,{auto_skip_6_SUITE,tc1}},
+ {?eh,tc_done,{auto_skip_6_SUITE,tc1,ok}},
+ {?eh,test_stats,{3,0,{0,11}}},
+ [{?eh,tc_start,{auto_skip_6_SUITE,{init_per_group,g4,[]}}},
+ {?eh,tc_done,{auto_skip_6_SUITE,{init_per_group,g4,[]},
+ {failed,{error,{group,g4,failed}}}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_6_SUITE,tc3,{failed,{auto_skip_6_SUITE,init_per_group,
+ {'EXIT',{group,g4,failed}}}}}},
+ {?eh,test_stats,{3,0,{0,12}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_6_SUITE,tc4,{failed,{auto_skip_6_SUITE,init_per_group,
+ {'EXIT',{group,g4,failed}}}}}},
+ {?eh,test_stats,{3,0,{0,13}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_6_SUITE,end_per_group,{failed,{auto_skip_6_SUITE,init_per_group,
+ {'EXIT',{group,g4,failed}}}}}}],
+ {?eh,tc_start,{auto_skip_6_SUITE,tc2}},
+ {?eh,tc_done,{auto_skip_6_SUITE,tc2,ok}},
+ {?eh,test_stats,{4,0,{0,13}}},
+ {?eh,tc_start,{auto_skip_6_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{auto_skip_6_SUITE,{end_per_group,g3,[]},ok}}],
+
+ {?eh,tc_start,{auto_skip_6_SUITE,end_per_suite}},
+ {?eh,tc_done,{auto_skip_6_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{auto_skip_7_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_7_SUITE,init_per_suite,ok}},
+ {?eh,tc_auto_skip,
+ {auto_skip_7_SUITE,tc1,{failed,{auto_skip_7_SUITE,init_per_suite,bad_return}}}},
+ {?eh,test_stats,{4,0,{0,14}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_7_SUITE,tc2,{failed,{auto_skip_7_SUITE,init_per_suite,bad_return}}}},
+ {?eh,test_stats,{4,0,{0,15}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_7_SUITE,end_per_suite,{failed,{auto_skip_7_SUITE,init_per_suite,bad_return}}}},
+
+ {?eh,tc_start,{auto_skip_8_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_8_SUITE,init_per_suite,ok}},
+ {?eh,tc_auto_skip,
+ {auto_skip_8_SUITE,tc1,{failed,{auto_skip_8_SUITE,init_per_suite,bad_return}}}},
+ {?eh,test_stats,{4,0,{0,16}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_8_SUITE,tc2,{failed,{auto_skip_8_SUITE,init_per_suite,bad_return}}}},
+ {?eh,test_stats,{4,0,{0,17}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_8_SUITE,end_per_suite,{failed,{auto_skip_8_SUITE,init_per_suite,bad_return}}}},
+
+ {?eh,tc_start,{auto_skip_9_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_9_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{auto_skip_9_SUITE,tc1}},
+ {?eh,tc_done,{auto_skip_9_SUITE,tc1,ok}},
+ {?eh,test_stats,{5,0,{0,17}}},
+ {?eh,tc_start,{auto_skip_9_SUITE,tc2}},
+ {?eh,tc_done,{auto_skip_9_SUITE,tc2,
+ {skipped,{failed,{auto_skip_9_SUITE,init_per_testcase,bad_return}}}}},
+ {?eh,test_stats,{5,0,{0,18}}},
+
+ [{?eh,tc_start,{auto_skip_9_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{auto_skip_9_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_start,{auto_skip_9_SUITE,tc3}},
+ {?eh,tc_done,{auto_skip_9_SUITE,tc3,ok}},
+ {?eh,test_stats,{6,0,{0,18}}},
+ {?eh,tc_start,{auto_skip_9_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{auto_skip_9_SUITE,{end_per_group,g1,[]},ok}}],
+
+ [{?eh,tc_start,{auto_skip_9_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{auto_skip_9_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_start,{auto_skip_9_SUITE,tc4}},
+ {?eh,tc_done,{auto_skip_9_SUITE,tc4,ok}},
+ {?eh,test_stats,{7,0,{0,18}}},
+ {?eh,tc_start,{auto_skip_9_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{auto_skip_9_SUITE,{end_per_group,g2,[]},ok}}],
+
+ [{?eh,tc_start,{auto_skip_9_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{auto_skip_9_SUITE,{init_per_group,g3,[]},ok}},
+ {?eh,tc_start,{auto_skip_9_SUITE,tc5}},
+ {?eh,tc_done,{auto_skip_9_SUITE,tc5,
+ {skipped,{failed,{auto_skip_9_SUITE,init_per_testcase,bad_return}}}}},
+ {?eh,test_stats,{7,0,{0,19}}},
+ {?eh,tc_start,{auto_skip_9_SUITE,{end_per_group,g3,[]}}},
+ {?eh,tc_done,{auto_skip_9_SUITE,{end_per_group,g3,[]},ok}}],
+
+ {parallel,
+ [{?eh,tc_start,
+ {auto_skip_9_SUITE,{init_per_group,g4,[parallel]}}},
+ {?eh,tc_done,
+ {auto_skip_9_SUITE,{init_per_group,g4,[parallel]},ok}},
+ {?eh,tc_start,{auto_skip_9_SUITE,tc6}},
+ {?eh,tc_done,{auto_skip_9_SUITE,tc6,ok}},
+ {parallel,
+ [{?eh,tc_start,
+ {auto_skip_9_SUITE,{init_per_group,g5,[parallel]}}},
+ {?eh,tc_done,
+ {auto_skip_9_SUITE,{init_per_group,g5,[parallel]},ok}},
+ {?eh,tc_start,{auto_skip_9_SUITE,tc8}},
+ {?eh,tc_done,
+ {auto_skip_9_SUITE,tc8,
+ {skipped,{failed,{auto_skip_9_SUITE,init_per_testcase,
+ {{badmatch,undefined},
+ [{auto_skip_9_SUITE,init_per_testcase,2},
+ {test_server,my_apply,3},
+ {test_server,init_per_testcase,3},
+ {test_server,run_test_case_eval1,6},
+ {test_server,run_test_case_eval,8}]}}}}}},
+ {?eh,tc_start,
+ {auto_skip_9_SUITE,{end_per_group,g5,[parallel]}}},
+ {?eh,tc_done,
+ {auto_skip_9_SUITE,{end_per_group,g5,[parallel]},ok}}]},
+
+ {?eh,tc_start,{auto_skip_9_SUITE,tc7}},
+ {?eh,tc_done,{auto_skip_9_SUITE,tc7,ok}},
+ {?eh,test_stats,{9,0,{0,20}}},
+ {?eh,tc_start,
+ {auto_skip_9_SUITE,{end_per_group,g4,[parallel]}}},
+ {?eh,tc_done,
+ {auto_skip_9_SUITE,{end_per_group,g4,[parallel]},ok}}]},
+
+ {?eh,tc_start,{auto_skip_9_SUITE,end_per_suite}},
+ {?eh,tc_done,{auto_skip_9_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{auto_skip_10_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_10_SUITE,init_per_suite,
+ {skipped,
+ {require_failed_in_suite0,
+ {not_available,undefined_config_variable}}}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_10_SUITE,tc1,
+ {require_failed_in_suite0,{not_available,undefined_config_variable}}}},
+ {?eh,test_stats,{9,0,{0,21}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_10_SUITE,tc2,
+ {require_failed_in_suite0,{not_available,undefined_config_variable}}}},
+ {?eh,test_stats,{9,0,{0,22}}},
+ {?eh,tc_auto_skip,
+ {auto_skip_10_SUITE,end_per_suite,
+ {require_failed_in_suite0,{not_available,undefined_config_variable}}}},
+
+ {?eh,tc_start,{auto_skip_11_SUITE,init_per_suite}},
+ {?eh,tc_done,{auto_skip_11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{auto_skip_11_SUITE,tc1}},
+ {?eh,tc_done,{auto_skip_11_SUITE,tc1,
+ {skipped,{require_failed,{not_available,undefined_config_variable}}}}},
+ {?eh,test_stats,{9,0,{0,23}}},
+ {?eh,tc_start,{auto_skip_11_SUITE,tc2}},
+ {?eh,tc_done,{auto_skip_11_SUITE,tc2,ok}},
+ {?eh,test_stats,{10,0,{0,23}}},
+
+ {parallel,
+ [{?eh,tc_start,
+ {auto_skip_11_SUITE,{init_per_group,g1,[parallel]}}},
+ {?eh,tc_done,
+ {auto_skip_11_SUITE,{init_per_group,g1,[parallel]},ok}},
+ {parallel,
+ [{?eh,tc_start,
+ {auto_skip_11_SUITE,{init_per_group,g2,[parallel]}}},
+ {?eh,tc_done,
+ {auto_skip_11_SUITE,{init_per_group,g2,[parallel]},ok}},
+ {?eh,tc_start,{auto_skip_11_SUITE,tc3}},
+ {?eh,tc_done,
+ {auto_skip_11_SUITE,tc3,
+ {skipped,{require_failed,{not_available,undefined_config_variable}}}}},
+ {?eh,test_stats,{10,0,{0,24}}},
+ {?eh,tc_start,
+ {auto_skip_11_SUITE,{end_per_group,g2,[parallel]}}},
+ {?eh,tc_done,
+ {auto_skip_11_SUITE,{end_per_group,g2,[parallel]},ok}}]},
+ {?eh,tc_start,
+ {auto_skip_11_SUITE,{end_per_group,g1,[parallel]}}},
+ {?eh,tc_done,
+ {auto_skip_11_SUITE,{end_per_group,g1,[parallel]},ok}}]},
+
+ {?eh,tc_start,{auto_skip_11_SUITE,end_per_suite}},
+ {?eh,tc_done,{auto_skip_11_SUITE,end_per_suite,ok}},
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(user_skip) ->
+ [{?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{5,5,27}},
+
+ {?eh,tc_start,{user_skip_1_SUITE,init_per_suite}},
+ {?eh,tc_done,
+ {user_skip_1_SUITE,init_per_suite,{skipped,"Whole suite skipped"}}},
+ {?eh,tc_auto_skip,
+ {user_skip_1_SUITE,tc1,"Whole suite skipped"}},
+ {?eh,test_stats,{0,0,{0,1}}},
+ {?eh,tc_auto_skip,
+ {user_skip_1_SUITE,tc2,"Whole suite skipped"}},
+ {?eh,test_stats,{0,0,{0,2}}},
+ {?eh,tc_auto_skip,
+ {user_skip_1_SUITE,tc3,"Whole suite skipped"}},
+ {?eh,test_stats,{0,0,{0,3}}},
+ {?eh,tc_auto_skip,
+ {user_skip_1_SUITE,tc4,"Whole suite skipped"}},
+ {?eh,test_stats,{0,0,{0,4}}},
+ {?eh,tc_auto_skip,
+ {user_skip_1_SUITE,end_per_suite,"Whole suite skipped"}},
+
+ {?eh,tc_start,{user_skip_2_SUITE,init_per_suite}},
+ {?eh,tc_done,{user_skip_2_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{user_skip_2_SUITE,tc1}},
+ {?eh,tc_done,{user_skip_2_SUITE,tc1,{skipped,{tc1,skipped}}}},
+ {?eh,test_stats,{0,0,{1,4}}},
+
+ [{?eh,tc_start,{user_skip_2_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{user_skip_2_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_start,{user_skip_2_SUITE,tc2}},
+ {?eh,tc_done,{user_skip_2_SUITE,tc2,ok}},
+ {?eh,test_stats,{1,0,{1,4}}},
+ {?eh,tc_start,{user_skip_2_SUITE,tc3}},
+ {?eh,tc_done,{user_skip_2_SUITE,tc3,{skipped,{tc3,skipped}}}},
+ {?eh,test_stats,{1,0,{2,4}}},
+ {?eh,tc_start,{user_skip_2_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{user_skip_2_SUITE,{end_per_group,g1,[]},ok}}],
+
+ {?eh,tc_start,{user_skip_2_SUITE,tc4}},
+ {?eh,tc_done,{user_skip_2_SUITE,tc4,ok}},
+ {?eh,test_stats,{2,0,{2,4}}},
+ {?eh,tc_start,{user_skip_2_SUITE,end_per_suite}},
+ {?eh,tc_done,{user_skip_2_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{user_skip_3_SUITE,init_per_suite}},
+ {?eh,tc_done,{user_skip_3_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{user_skip_3_SUITE,tc1}},
+ {?eh,tc_done,{user_skip_3_SUITE,tc1,{skipped,"Test case skipped"}}},
+ {?eh,test_stats,{2,0,{3,4}}},
+
+ [{?eh,tc_start,{user_skip_3_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{user_skip_3_SUITE,{init_per_group,g1,[]},ok}},
+ {?eh,tc_start,{user_skip_3_SUITE,tc2}},
+ {?eh,tc_done,{user_skip_3_SUITE,tc2,ok}},
+ {?eh,test_stats,{3,0,{3,4}}},
+ {?eh,tc_start,{user_skip_3_SUITE,tc3}},
+ {?eh,tc_done,{user_skip_3_SUITE,tc3,{skipped,"Test case skipped"}}},
+ {?eh,test_stats,{3,0,{4,4}}},
+ {?eh,tc_start,{user_skip_3_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{user_skip_3_SUITE,{end_per_group,g1,[]},ok}}],
+
+ {?eh,tc_start,{user_skip_3_SUITE,tc4}},
+ {?eh,tc_done,{user_skip_3_SUITE,tc4,
+ {skipped,{proc_info,{{current_function,{user_skip_3_SUITE,tc4,1}},
+ {initial_call,{erlang,apply,2}}}}}}},
+ {?eh,test_stats,{3,0,{5,4}}},
+ {?eh,tc_start,{user_skip_3_SUITE,end_per_suite}},
+ {?eh,tc_done,{user_skip_3_SUITE,end_per_suite,ok}},
+
+ {?eh,tc_start,{user_skip_4_SUITE,init_per_suite}},
+ {?eh,tc_done,{user_skip_4_SUITE,init_per_suite,ok}},
+
+ [{?eh,tc_start,{user_skip_4_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{user_skip_4_SUITE,{init_per_group,g1,[]},{skipped,"Group skipped"}}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,tc1,"Group skipped"}},
+ {?eh,test_stats,{3,0,{5,5}}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,tc2,"Group skipped"}},
+ {?eh,test_stats,{3,0,{5,6}}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,end_per_group,"Group skipped"}}],
+
+ [{?eh,tc_start,{user_skip_4_SUITE,{init_per_group,g2,[]}}},
+ {?eh,tc_done,{user_skip_4_SUITE,{init_per_group,g2,[]},ok}},
+ {?eh,tc_start,{user_skip_4_SUITE,tc3}},
+ {?eh,tc_done,{user_skip_4_SUITE,tc3,ok}},
+ {?eh,test_stats,{4,0,{5,6}}},
+ {?eh,tc_start,{user_skip_4_SUITE,tc4}},
+ {?eh,tc_done,{user_skip_4_SUITE,tc4,ok}},
+ {?eh,test_stats,{5,0,{5,6}}},
+ {?eh,tc_start,{user_skip_4_SUITE,{end_per_group,g2,[]}}},
+ {?eh,tc_done,{user_skip_4_SUITE,{end_per_group,g2,[]},ok}}],
+
+ [{?eh,tc_start,{user_skip_4_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{user_skip_4_SUITE,{init_per_group,g3,[]},{skipped,"Group skipped"}}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,tc5,"Group skipped"}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,tc6,"Group skipped"}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,tc7,"Group skipped"}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,tc8,"Group skipped"}},
+ {?eh,test_stats,{5,0,{5,10}}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,end_per_group,"Group skipped"}}],
+
+ [{?eh,tc_start,{user_skip_4_SUITE,{init_per_group,g5,[]}}},
+ {?eh,tc_done,{user_skip_4_SUITE,{init_per_group,g5,[]},ok}},
+ {?eh,tc_start,{user_skip_4_SUITE,tc9}},
+ {?eh,tc_done,{user_skip_4_SUITE,tc9,ok}},
+ {?eh,test_stats,{6,0,{5,10}}},
+ [{?eh,tc_start,{user_skip_4_SUITE,{init_per_group,g6,[]}}},
+ {?eh,tc_done,{user_skip_4_SUITE,{init_per_group,g6,[]},{skipped,"Group skipped"}}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,tc10,"Group skipped"}},
+ {?eh,test_stats,{6,0,{5,11}}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,tc11,"Group skipped"}},
+ {?eh,test_stats,{6,0,{5,12}}},
+ {?eh,tc_auto_skip,{user_skip_4_SUITE,end_per_group,"Group skipped"}}],
+ {?eh,tc_start,{user_skip_4_SUITE,{end_per_group,g5,[]}}},
+ {?eh,tc_done,{user_skip_4_SUITE,{end_per_group,g5,[]},ok}}],
+
+ {?eh,tc_start,{user_skip_4_SUITE,end_per_suite}},
+ {?eh,tc_done,{user_skip_4_SUITE,end_per_suite,ok}},
+
+ {ct_test_support_eh,tc_start,{user_skip_5_SUITE,init_per_suite}},
+ {?eh,tc_done,{user_skip_5_SUITE,init_per_suite,
+ {skipped,{bad,'Whole suite skipped'}}}},
+ {?eh,tc_auto_skip,{user_skip_5_SUITE,tc1,{bad,'Whole suite skipped'}}},
+ {?eh,test_stats,{6,0,{5,13}}},
+ {?eh,tc_auto_skip,{user_skip_5_SUITE,tc2,{bad,'Whole suite skipped'}}},
+ {?eh,test_stats,{6,0,{5,14}}},
+ {?eh,tc_auto_skip,{user_skip_5_SUITE,tc3,{bad,'Whole suite skipped'}}},
+ {?eh,test_stats,{6,0,{5,15}}},
+ {?eh,tc_auto_skip,{user_skip_5_SUITE,tc4,{bad,'Whole suite skipped'}}},
+ {?eh,test_stats,{6,0,{5,16}}},
+ {?eh,tc_auto_skip,{user_skip_5_SUITE,end_per_suite,{bad,'Whole suite skipped'}}},
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_10_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_10_SUITE.erl
new file mode 100644
index 0000000000..b93c68e126
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_10_SUITE.erl
@@ -0,0 +1,130 @@
+%%
+%% %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%
+%%
+-module(auto_skip_10_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{require,undefined_config_variable}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_11_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_11_SUITE.erl
new file mode 100644
index 0000000000..c0a662f4b2
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_11_SUITE.erl
@@ -0,0 +1,136 @@
+%%
+%% %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%
+%%
+-module(auto_skip_11_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[parallel],[{g2,[parallel],[tc3]}]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2,{group,g1}].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [{require,undefined_config_variable}].
+
+tc3() ->
+ [{require,undefined_config_variable}].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ exit(should_be_auto_skipped).
+
+tc2(_Config) ->
+ ok.
+
+tc3(_Config) ->
+ exit(should_be_auto_skipped).
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_1_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_1_SUITE.erl
new file mode 100644
index 0000000000..247e478fa3
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_1_SUITE.erl
@@ -0,0 +1,130 @@
+%%
+%% %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%
+%%
+-module(auto_skip_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(_Config) ->
+ exit(init_per_suite_failed).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_2_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_2_SUITE.erl
new file mode 100644
index 0000000000..3d332d2a28
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_2_SUITE.erl
@@ -0,0 +1,127 @@
+%%
+%% %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%
+%%
+-module(auto_skip_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(_Config) ->
+ exit(init_per_suite_failed).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc1]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [{group,g1}].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_3_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_3_SUITE.erl
new file mode 100644
index 0000000000..cb64cb76c5
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_3_SUITE.erl
@@ -0,0 +1,132 @@
+%%
+%% %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%
+%%
+-module(auto_skip_3_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(tc1, _Config) ->
+ exit({init_per_testcase,tc1,failed});
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_4_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_4_SUITE.erl
new file mode 100644
index 0000000000..825846cd55
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_4_SUITE.erl
@@ -0,0 +1,126 @@
+%%
+%% %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%
+%%
+-module(auto_skip_4_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,1}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(tc1, Config) ->
+ timer:sleep(5000),
+ Config;
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_5_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_5_SUITE.erl
new file mode 100644
index 0000000000..2cf07928bb
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_5_SUITE.erl
@@ -0,0 +1,123 @@
+%%
+%% %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%
+%%
+-module(auto_skip_5_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,1}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(GroupName, _Config) ->
+ exit({group,GroupName,failed}).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc1,tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [{group,g1}].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_6_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_6_SUITE.erl
new file mode 100644
index 0000000000..c950fed6b7
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_6_SUITE.erl
@@ -0,0 +1,136 @@
+%%
+%% %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%
+%%
+-module(auto_skip_6_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,1}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(g1, _Config) ->
+ exit({group,g1,failed});
+init_per_group(g2, Config) ->
+ Config;
+init_per_group(g3, Config) ->
+ Config;
+init_per_group(g4, _Config) ->
+ exit({group,g4,failed}).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc1,{g2,[],[tc3,tc4]},tc2]},
+ {g3,[],[tc1,{g4,[],[tc3,tc4]},tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [{group,g1},{group,g3}].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
+
+tc3(_Config) ->
+ ok.
+
+tc4(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_7_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_7_SUITE.erl
new file mode 100644
index 0000000000..6146459bf2
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_7_SUITE.erl
@@ -0,0 +1,130 @@
+%%
+%% %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%
+%%
+-module(auto_skip_7_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_8_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_8_SUITE.erl
new file mode 100644
index 0000000000..462d6b4e79
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_8_SUITE.erl
@@ -0,0 +1,130 @@
+%%
+%% %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%
+%%
+-module(auto_skip_8_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ [{x,y,z}|Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
+
+tc2(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_9_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_9_SUITE.erl
new file mode 100644
index 0000000000..e2d6bcf7d6
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/auto_skip_9_SUITE.erl
@@ -0,0 +1,166 @@
+%%
+%% %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%
+%%
+-module(auto_skip_9_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(g1, Config) ->
+ ok;
+init_per_group(g2, Config) ->
+ [{x,y,z}|Config];
+init_per_group(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(tc2, Config) ->
+ {ok,Config};
+init_per_testcase(tc5, Config) ->
+ ok;
+init_per_testcase(tc8, Config) ->
+ huh = ?config(void, Config),
+ Config;
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc3]},
+ {g2,[],[tc4]},
+ {g3,[],[tc5]},
+ {g4,[parallel],[tc6,{group,g5},tc7]},
+ {g5,[parallel],[tc8]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,tc2,{group,g1},{group,g2},{group,g3},{group,g4}].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ct:comment("Should be ok"),
+ true.
+
+tc2(_Config) ->
+ exit("Should fail in init_per_testcase").
+
+tc3(Config) ->
+ ?config(data_dir, Config).
+
+tc4(Config) ->
+ ?config(data_dir, Config).
+
+tc5(_Config) ->
+ exit("Should fail in init_per_testcase").
+
+tc6(_Config) ->
+ done.
+
+tc7(_Config) ->
+ done.
+
+tc8(_Config) ->
+ exit("Should fail in init_per_testcase").
+
+
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_1_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_1_SUITE.erl
new file mode 100644
index 0000000000..60fc0f1122
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_1_SUITE.erl
@@ -0,0 +1,131 @@
+%%
+%% %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%
+%%
+-module(user_skip_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(_Config) ->
+ {skip,"Whole suite skipped"}.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2,tc3]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1, {group,g1}, tc4].
+
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
+
+tc3(_) ->
+ ok.
+
+tc4(_) ->
+ ok.
+
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_2_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_2_SUITE.erl
new file mode 100644
index 0000000000..91a046a531
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_2_SUITE.erl
@@ -0,0 +1,135 @@
+%%
+%% %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%
+%%
+-module(user_skip_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(tc1, _Config) ->
+ {skip,{tc1,skipped}};
+init_per_testcase(tc3, _Config) ->
+ {skip,{tc3,skipped}};
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2,tc3]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1, {group,g1}, tc4].
+
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
+
+tc3(_) ->
+ ok.
+
+tc4(_) ->
+ ok.
+
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_3_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_3_SUITE.erl
new file mode 100644
index 0000000000..c362117bba
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_3_SUITE.erl
@@ -0,0 +1,132 @@
+%%
+%% %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%
+%%
+-module(user_skip_3_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2,tc3]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1, {group,g1}, tc4].
+
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_) ->
+ {skip,"Test case skipped"}.
+
+tc2(_) ->
+ ok.
+
+tc3(_) ->
+ {skip,"Test case skipped"}.
+
+tc4(_) ->
+ {skip,{proc_info,{process_info(self(),current_function),
+ process_info(self(),initial_call)}}}.
+
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_4_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_4_SUITE.erl
new file mode 100644
index 0000000000..77fd5a2b5b
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_4_SUITE.erl
@@ -0,0 +1,152 @@
+%%
+%% %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%
+%%
+-module(user_skip_4_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(g1, _Config) ->
+ {skip,"Group skipped"};
+init_per_group(g3, _Config) ->
+ {skip,"Group skipped"};
+init_per_group(g6, _Config) ->
+ {skip,"Group skipped"};
+init_per_group(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc1,tc2]},
+ {g2,[],[tc3,tc4]},
+ {g3,[],[tc5,{g4,[],[tc6,tc7]},tc8]},
+ {g5,[],[tc9,{g6,[],[tc10,tc11]}]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [{group,g1}, {group,g2}, {group,g3}, {group,g5}].
+
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_) ->
+ ok.
+tc2(_) ->
+ ok.
+tc3(_) ->
+ ok.
+tc4(_) ->
+ ok.
+tc5(_) ->
+ ok.
+tc6(_) ->
+ ok.
+tc7(_) ->
+ ok.
+tc8(_) ->
+ ok.
+tc9(_) ->
+ ok.
+tc10(_) ->
+ ok.
+tc11(_) ->
+ ok.
+
+
diff --git a/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_5_SUITE.erl b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_5_SUITE.erl
new file mode 100644
index 0000000000..4bffa202d6
--- /dev/null
+++ b/lib/common_test/test/ct_skip_SUITE_data/skip/test/user_skip_5_SUITE.erl
@@ -0,0 +1,131 @@
+%%
+%% %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%
+%%
+-module(user_skip_5_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(_Config) ->
+ {skip,{bad,'Whole suite skipped'}}.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[tc2,tc3]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1, {group,g1}, tc4].
+
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_) ->
+ ok.
+
+tc2(_) ->
+ ok.
+
+tc3(_) ->
+ ok.
+
+tc4(_) ->
+ ok.
+
diff --git a/lib/common_test/test/ct_smoke_test_SUITE.erl b/lib/common_test/test/ct_smoke_test_SUITE.erl
new file mode 100644
index 0000000000..f1c695f614
--- /dev/null
+++ b/lib/common_test/test/ct_smoke_test_SUITE.erl
@@ -0,0 +1,569 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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_smoke_test_SUITE.erl
+%%%
+%%% Description: The purpose of this suite is to test that Common Test
+%%% can be started properly and that simple dummy test suites are
+%%% executed without unexpected crashes or hangings. The suites used
+%%% for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_smoke_test_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
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) -> Config1 | {skip,Reason}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the suite.
+%%
+%% 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) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> void()
+%%
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after the suite.
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) -> Config1 |
+%% {skip,Reason}
+%% TestCase = atom()
+%% Name of the test case that is about to run.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Initialization 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.
+%%--------------------------------------------------------------------
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> void()
+%%
+%% TestCase = atom()
+%% Name of the test case that is finished.
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after each test case.
+%%--------------------------------------------------------------------
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> Descr | TestCases | {skip,Reason}
+%%
+%% Clause = doc | suite
+%% Indicates expected return value.
+%% Descr = [string()] | []
+%% String that describes the test suite.
+%% TestCases = [TestCase]
+%% TestCase = atom()
+%% Name of a test case.
+%% Reason = term()
+%% The reason for skipping the test suite.
+%%
+%% Description: Returns a description of the test suite (doc) and a
+%% list of all test cases in the suite (suite).
+%%--------------------------------------------------------------------
+all(doc) ->
+ ["Run smoke tests of Common Test."];
+
+all(suite) ->
+ [dir1, dir2, dir1_2,
+ suite11, suite21, suite11_21,
+ tc111, tc211, tc111_112].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Arg) -> Descr | Spec | ok | exit() | {skip,Reason}
+%%
+%% Arg = doc | suite | Config
+%% Indicates expected behaviour and return value.
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Descr = [string()] | []
+%% String that describes the test case.
+%% Spec = [tuple()] | []
+%% A test specification.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Test case function. Returns a description of the test
+%% case (doc), then returns a test specification (suite),
+%% or performs the actual test (Config).
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+
+dir1(doc) ->
+ [];
+dir1(suite) ->
+ [];
+dir1(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Happy1 = filename:join(DataDir, "happy_1"),
+ Happy1Cfg = filename:join(Happy1, "cfg/config1.cfg"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy1Cfg}, {dir,Happy1}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(dir1,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(dir1),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+dir2(doc) ->
+ [];
+dir2(suite) ->
+ [];
+dir2(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Happy2 = filename:join(DataDir, "happy_2_test"),
+ Happy2Cfg = filename:join(DataDir, "happy_2_cfg/config1.cfg"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy2Cfg}, {dir,Happy2}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(dir2,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(dir2),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+dir1_2(doc) ->
+ [];
+dir1_2(suite) ->
+ [];
+dir1_2(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Happy1 = filename:join(DataDir, "happy_1"),
+ Happy2 = filename:join(DataDir, "happy_2_test"),
+ Happy1Cfg = filename:join(Happy1, "cfg/config1.cfg"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy1Cfg}, {dir,[Happy1,Happy2]}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(dir1_2,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(dir1_2),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+suite11(doc) ->
+ [];
+suite11(suite) ->
+ [];
+suite11(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Happy1 = filename:join(DataDir, "happy_1"),
+ Suite = filename:join(Happy1, "test/happy_11_SUITE"),
+ Happy1Cfg = filename:join(Happy1, "cfg/config1.cfg"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy1Cfg}, {suite,Suite}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(suite11,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(suite11),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+suite21(doc) ->
+ [];
+suite21(suite) ->
+ [];
+suite21(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Suite = filename:join(DataDir, "happy_2_test/happy_21_SUITE"),
+ Happy2Cfg = filename:join(DataDir, "happy_2_cfg/config1.cfg"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy2Cfg}, {suite,Suite}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(suite21,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(suite21),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+suite11_21(doc) ->
+ [];
+suite11_21(suite) ->
+ [];
+suite11_21(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Happy1 = filename:join(DataDir, "happy_1"),
+ Suite11 = filename:join(Happy1, "test/happy_11_SUITE"),
+ Happy1Cfg = filename:join(Happy1, "cfg/config1.cfg"),
+ Suite21 = filename:join(DataDir, "happy_2_test/happy_21_SUITE"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy1Cfg}, {suite,[Suite11,Suite21]}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(suite11_21,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(suite11_21),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+tc111(doc) ->
+ [];
+tc111(suite) ->
+ [];
+tc111(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Happy1 = filename:join(DataDir, "happy_1"),
+ Suite = filename:join(Happy1, "test/happy_11_SUITE"),
+ Happy1Cfg = filename:join(Happy1, "cfg/config1.cfg"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy1Cfg}, {suite,Suite},
+ {testcase,tc1}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(tc111,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(tc111),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+tc211(doc) ->
+ [];
+tc211(suite) ->
+ [];
+tc211(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Suite = filename:join(DataDir, "happy_2_test/happy_21_SUITE"),
+ Happy2Cfg = filename:join(DataDir, "happy_2_cfg/config1.cfg"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy2Cfg}, {suite,Suite},
+ {testcase,tc1}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(tc211,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(tc211),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+
+tc111_112(doc) ->
+ [];
+tc111_112(suite) ->
+ [];
+tc111_112(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ Happy1 = filename:join(DataDir, "happy_1"),
+ Suite = filename:join(Happy1, "test/happy_11_SUITE"),
+ Happy1Cfg = filename:join(Happy1, "cfg/config1.cfg"),
+
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{config,Happy1Cfg}, {suite,Suite},
+ {testcase,[tc1,tc2]}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(tc111_112,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = test_events(tc111_112),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+eh_opts(Config) ->
+ Level = ?config(trace_level, Config),
+ [{event_handler,{?eh,[{cbm,ct_test_support},{trace_level,Level}]}}].
+
+
+test_events(Test) when Test == dir1 ; Test == dir2 ;
+ Test == suite11 ; Test == suite21 ->
+ Suite = if Test == dir1 ; Test == suite11 -> happy_11_SUITE;
+ true -> happy_21_SUITE
+ end,
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,8}},
+ {?eh,tc_start,{Suite,init_per_suite}},
+ {?eh,tc_done,{Suite,init_per_suite,ok}},
+ {?eh,tc_start,{Suite,tc1}},
+ {?eh,tc_done,{Suite,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{Suite,tc2}},
+ {?eh,tc_done,{Suite,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{Suite,seq1_tc1}},
+ {?eh,tc_done,{Suite,seq1_tc1,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{Suite,seq1_tc2}},
+ {?eh,tc_done,{Suite,seq1_tc2,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{Suite,tc3}},
+ {?eh,tc_done,{Suite,tc3,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,{Suite,seq2_tc1}},
+ {?eh,tc_done,{Suite,seq2_tc1,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+ {?eh,tc_start,{Suite,seq2_tc2}},
+ {?eh,tc_done,{Suite,seq2_tc2,ok}},
+ {?eh,test_stats,{7,0,{0,0}}},
+ {?eh,tc_start,{Suite,tc4}},
+ {?eh,tc_done,
+ {Suite,tc4,{skipped,"Skipping this one"}}},
+ {?eh,test_stats,{7,0,{1,0}}},
+ {?eh,tc_start,{Suite,end_per_suite}},
+ {?eh,tc_done,{Suite,end_per_suite,ips_data}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+test_events(Test) when Test == dir1_2 ; Test == suite11_21 ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{2,2,16}},
+ {?eh,tc_start,{happy_11_SUITE,init_per_suite}},
+ {?eh,tc_done,{happy_11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{happy_11_SUITE,tc1}},
+ {?eh,tc_done,{happy_11_SUITE,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,tc2}},
+ {?eh,tc_done,{happy_11_SUITE,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,seq1_tc1}},
+ {?eh,tc_done,{happy_11_SUITE,seq1_tc1,ok}},
+ {?eh,test_stats,{3,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,seq1_tc2}},
+ {?eh,tc_done,{happy_11_SUITE,seq1_tc2,ok}},
+ {?eh,test_stats,{4,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,tc3}},
+ {?eh,tc_done,{happy_11_SUITE,tc3,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,seq2_tc1}},
+ {?eh,tc_done,{happy_11_SUITE,seq2_tc1,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,seq2_tc2}},
+ {?eh,tc_done,{happy_11_SUITE,seq2_tc2,ok}},
+ {?eh,test_stats,{7,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,tc4}},
+ {?eh,tc_done,
+ {happy_11_SUITE,tc4,{skipped,"Skipping this one"}}},
+ {?eh,test_stats,{7,0,{1,0}}},
+ {?eh,tc_start,{happy_11_SUITE,end_per_suite}},
+ {?eh,tc_done,{happy_11_SUITE,end_per_suite,ips_data}},
+ {?eh,tc_start,{happy_21_SUITE,init_per_suite}},
+ {?eh,tc_done,{happy_21_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{happy_21_SUITE,tc1}},
+ {?eh,tc_done,{happy_21_SUITE,tc1,ok}},
+ {?eh,test_stats,{8,0,{1,0}}},
+ {?eh,tc_start,{happy_21_SUITE,tc2}},
+ {?eh,tc_done,{happy_21_SUITE,tc2,ok}},
+ {?eh,test_stats,{9,0,{1,0}}},
+ {?eh,tc_start,{happy_21_SUITE,seq1_tc1}},
+ {?eh,tc_done,{happy_21_SUITE,seq1_tc1,ok}},
+ {?eh,test_stats,{10,0,{1,0}}},
+ {?eh,tc_start,{happy_21_SUITE,seq1_tc2}},
+ {?eh,tc_done,{happy_21_SUITE,seq1_tc2,ok}},
+ {?eh,test_stats,{11,0,{1,0}}},
+ {?eh,tc_start,{happy_21_SUITE,tc3}},
+ {?eh,tc_done,{happy_21_SUITE,tc3,ok}},
+ {?eh,test_stats,{12,0,{1,0}}},
+ {?eh,tc_start,{happy_21_SUITE,seq2_tc1}},
+ {?eh,tc_done,{happy_21_SUITE,seq2_tc1,ok}},
+ {?eh,test_stats,{13,0,{1,0}}},
+ {?eh,tc_start,{happy_21_SUITE,seq2_tc2}},
+ {?eh,tc_done,{happy_21_SUITE,seq2_tc2,ok}},
+ {?eh,test_stats,{14,0,{1,0}}},
+ {?eh,tc_start,{happy_21_SUITE,tc4}},
+ {?eh,tc_done,
+ {happy_21_SUITE,tc4,{skipped,"Skipping this one"}}},
+ {?eh,test_stats,{14,0,{2,0}}},
+ {?eh,tc_start,{happy_21_SUITE,end_per_suite}},
+ {?eh,tc_done,{happy_21_SUITE,end_per_suite,ips_data}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(Test) when Test == tc111 ; Test == tc211 ->
+ Suite = if Test == tc111 -> happy_11_SUITE; true -> happy_21_SUITE end,
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{Suite,init_per_suite}},
+ {?eh,tc_done,{Suite,init_per_suite,ok}},
+ {?eh,tc_start,{Suite,tc1}},
+ {?eh,tc_done,{Suite,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{Suite,end_per_suite}},
+ {?eh,tc_done,{Suite,end_per_suite,ips_data}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(tc111_112) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,2}},
+ {?eh,tc_start,{happy_11_SUITE,init_per_suite}},
+ {?eh,tc_done,{happy_11_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{happy_11_SUITE,tc1}},
+ {?eh,tc_done,{happy_11_SUITE,tc1,ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,tc2}},
+ {?eh,tc_done,{happy_11_SUITE,tc2,ok}},
+ {?eh,test_stats,{2,0,{0,0}}},
+ {?eh,tc_start,{happy_11_SUITE,end_per_suite}},
+ {?eh,tc_done,{happy_11_SUITE,end_per_suite,ips_data}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_smoke_test_SUITE_data/happy_1/cfg/config1.cfg b/lib/common_test/test/ct_smoke_test_SUITE_data/happy_1/cfg/config1.cfg
new file mode 100644
index 0000000000..3d6e5622f5
--- /dev/null
+++ b/lib/common_test/test/ct_smoke_test_SUITE_data/happy_1/cfg/config1.cfg
@@ -0,0 +1,5 @@
+{v1, apple}.
+{v2, plum}.
+{v3, [{v31, cherry},
+ {v32, banana},
+ {v33, coconut}]}.
diff --git a/lib/common_test/test/ct_smoke_test_SUITE_data/happy_1/test/happy_11_SUITE.erl b/lib/common_test/test/ct_smoke_test_SUITE_data/happy_1/test/happy_11_SUITE.erl
new file mode 100644
index 0000000000..f33f0934cb
--- /dev/null
+++ b/lib/common_test/test/ct_smoke_test_SUITE_data/happy_1/test/happy_11_SUITE.erl
@@ -0,0 +1,196 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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 : happy_11_SUITE.erl
+%%% Description : Happy test of all common_test callback functions.
+%%%-------------------------------------------------------------------
+-module(happy_11_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% COMMON TEST CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%%
+%% Info = [tuple()]
+%% List of key/value pairs.
+%%
+%% Description: Returns list of tuples to set default properties
+%% for the suite.
+%%
+%% Note: The suite/0 function is only meant to be used to return
+%% default data values, not perform any other operations.
+%%--------------------------------------------------------------------
+suite() ->
+ [
+ {timetrap,{seconds,10}},
+ {require, v1},
+ {userdata, {info,"Happy test of CT callback functions."}}
+ ].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the suite.
+%%
+%% Description: Initialization before the suite.
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ [{ips,ips_data} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after the suite.
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ ips_data = ?config(ips, Config).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%%
+%% TestCase = atom()
+%% Name of the test case that is about to run.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Initialization 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.
+%%--------------------------------------------------------------------
+init_per_testcase(TestCase, Config) ->
+ [{TestCase,{TestCase,data}} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%%
+%% TestCase = atom()
+%% Name of the test case that is finished.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after each test case.
+%%--------------------------------------------------------------------
+end_per_testcase(TestCase, Config) ->
+ {TestCase,data} = ?config(TestCase, Config).
+
+%%--------------------------------------------------------------------
+%% Function: sequences() -> Sequences
+%%
+%% Sequences = [{SeqName,TestCases}]
+%% SeqName = atom()
+%% Name of a sequence.
+%% TestCases = [atom()]
+%% List of test cases that are part of the sequence
+%%
+%% Description: Specifies test case sequences.
+%%--------------------------------------------------------------------
+sequences() ->
+ [{seq1,[seq1_tc1, seq1_tc2]},
+ {seq2,[seq2_tc1, seq2_tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> TestCases | {skip,Reason}
+%%
+%% TestCases = [TestCase | {sequence,SeqName}]
+%% TestCase = atom()
+%% Name of a test case.
+%% SeqName = atom()
+%% Name of a test case sequence.
+%% Reason = term()
+%% The reason for skipping all test cases.
+%%
+%% Description: Returns the list of test cases that are to be executed.
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,
+ tc2,
+ seq1,
+ tc3,
+ seq2,
+ tc4].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+tc1() ->
+ [{userdata,{info, "This is a testcase"}}].
+
+tc1(Config) ->
+ ips_data = ?config(ips, Config),
+ {tc1,data} = ?config(tc1, Config),
+ apple = ct:get_config(v1),
+ ok.
+
+tc2() ->
+ [{timetrap,5000},
+ {require,v2}].
+
+tc2(Config) ->
+ ips_data = ?config(ips, Config),
+ undefined = ?config(tc1, Config),
+ {tc2,data} = ?config(tc2, Config),
+ plum = ct:get_config(v2),
+ ok.
+
+tc3() ->
+ [{timetrap,{minutes,1}}].
+
+tc3(_Config) ->
+ ok = ct:require(v3),
+ [{v31, cherry},{v32, banana},{v33, coconut}] = ct:get_config(v3),
+ banana = ct:get_config({v3,v32}),
+ ok.
+
+tc4(Config) ->
+ {skip,"Skipping this one"}.
+
+seq1_tc1(_) ->
+ ok.
+seq1_tc2(_) ->
+ ok.
+
+seq2_tc1(_) ->
+ ok.
+seq2_tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_smoke_test_SUITE_data/happy_2_cfg/config1.cfg b/lib/common_test/test/ct_smoke_test_SUITE_data/happy_2_cfg/config1.cfg
new file mode 100644
index 0000000000..3d6e5622f5
--- /dev/null
+++ b/lib/common_test/test/ct_smoke_test_SUITE_data/happy_2_cfg/config1.cfg
@@ -0,0 +1,5 @@
+{v1, apple}.
+{v2, plum}.
+{v3, [{v31, cherry},
+ {v32, banana},
+ {v33, coconut}]}.
diff --git a/lib/common_test/test/ct_smoke_test_SUITE_data/happy_2_test/happy_21_SUITE.erl b/lib/common_test/test/ct_smoke_test_SUITE_data/happy_2_test/happy_21_SUITE.erl
new file mode 100644
index 0000000000..33d18006f9
--- /dev/null
+++ b/lib/common_test/test/ct_smoke_test_SUITE_data/happy_2_test/happy_21_SUITE.erl
@@ -0,0 +1,196 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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 : happy_21_SUITE.erl
+%%% Description : Happy test of all common_test callback functions.
+%%%-------------------------------------------------------------------
+-module(happy_21_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% COMMON TEST CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%%
+%% Info = [tuple()]
+%% List of key/value pairs.
+%%
+%% Description: Returns list of tuples to set default properties
+%% for the suite.
+%%
+%% Note: The suite/0 function is only meant to be used to return
+%% default data values, not perform any other operations.
+%%--------------------------------------------------------------------
+suite() ->
+ [
+ {timetrap,{seconds,10}},
+ {require, v1},
+ {userdata, {info,"Happy test of CT callback functions."}}
+ ].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the suite.
+%%
+%% Description: Initialization before the suite.
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ [{ips,ips_data} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after the suite.
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ ips_data = ?config(ips, Config).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%%
+%% TestCase = atom()
+%% Name of the test case that is about to run.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Initialization 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.
+%%--------------------------------------------------------------------
+init_per_testcase(TestCase, Config) ->
+ [{TestCase,{TestCase,data}} | Config].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%%
+%% TestCase = atom()
+%% Name of the test case that is finished.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after each test case.
+%%--------------------------------------------------------------------
+end_per_testcase(TestCase, Config) ->
+ {TestCase,data} = ?config(TestCase, Config).
+
+%%--------------------------------------------------------------------
+%% Function: sequences() -> Sequences
+%%
+%% Sequences = [{SeqName,TestCases}]
+%% SeqName = atom()
+%% Name of a sequence.
+%% TestCases = [atom()]
+%% List of test cases that are part of the sequence
+%%
+%% Description: Specifies test case sequences.
+%%--------------------------------------------------------------------
+sequences() ->
+ [{seq1,[seq1_tc1, seq1_tc2]},
+ {seq2,[seq2_tc1, seq2_tc2]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> TestCases | {skip,Reason}
+%%
+%% TestCases = [TestCase | {sequence,SeqName}]
+%% TestCase = atom()
+%% Name of a test case.
+%% SeqName = atom()
+%% Name of a test case sequence.
+%% Reason = term()
+%% The reason for skipping all test cases.
+%%
+%% Description: Returns the list of test cases that are to be executed.
+%%--------------------------------------------------------------------
+all() ->
+ [tc1,
+ tc2,
+ seq1,
+ tc3,
+ seq2,
+ tc4].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+tc1() ->
+ [{userdata,{info, "This is a testcase"}}].
+
+tc1(Config) ->
+ ips_data = ?config(ips, Config),
+ {tc1,data} = ?config(tc1, Config),
+ apple = ct:get_config(v1),
+ ok.
+
+tc2() ->
+ [{timetrap,5000},
+ {require,v2}].
+
+tc2(Config) ->
+ ips_data = ?config(ips, Config),
+ undefined = ?config(tc1, Config),
+ {tc2,data} = ?config(tc2, Config),
+ plum = ct:get_config(v2),
+ ok.
+
+tc3() ->
+ [{timetrap,{minutes,1}}].
+
+tc3(_Config) ->
+ ok = ct:require(v3),
+ [{v31, cherry},{v32, banana},{v33, coconut}] = ct:get_config(v3),
+ banana = ct:get_config({v3,v32}),
+ ok.
+
+tc4(Config) ->
+ {skip,"Skipping this one"}.
+
+seq1_tc1(_) ->
+ ok.
+seq1_tc2(_) ->
+ ok.
+
+seq2_tc1(_) ->
+ ok.
+seq2_tc2(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE.erl
new file mode 100644
index 0000000000..069f8c75fc
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE.erl
@@ -0,0 +1,253 @@
+%%
+%% %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_test_server_if_SUITE
+%%%
+%%% Description:
+%%% Test the test_server -> framework interface.
+%%%
+%%% The suites used for the test are located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_test_server_if_1_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) ->
+ Config1 = ct_test_support:init_per_suite(Config),
+ Config1.
+
+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).
+
+all(doc) ->
+ [""];
+
+all(suite) ->
+ [
+ ts_if_1
+ ].
+
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+ts_if_1(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+ TODir = filename:join(DataDir, "test_server_if"),
+ Level = ?config(trace_level, Config),
+ TestSpec = [
+ {event_handler,?eh,[{cbm,ct_test_support},{trace_level,Level}]},
+ {suites,TODir,[ts_if_1_SUITE,ts_if_2_SUITE,ts_if_3_SUITE,
+ ts_if_4_SUITE,ts_if_5_SUITE,ts_if_6_SUITE,
+ ts_if_7_SUITE,ts_if_8_SUITE]},
+ {skip_suites,TODir,[skipped_by_spec_1_SUITE],"should be skipped"},
+ {skip_cases,TODir,skipped_by_spec_2_SUITE,[tc1],"should be skipped"}
+ ],
+
+ TestSpecName = ct_test_support:write_testspec(TestSpec, PrivDir, "ts_if_1_spec"),
+ {Opts,ERPid} = setup({spec,TestSpecName}, Config),
+ ok = ct_test_support:run(ct, run_test, [Opts], Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(ts_if_1,
+ reformat(Events, ?eh),
+ PrivDir),
+
+ TestEvents = test_events(ts_if_1),
+ 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 ++ [Test,{event_handler,{?eh,EvHArgs}}],
+ Opts = [Test | Opts0],
+ 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
+%%%-----------------------------------------------------------------
+test_events(ts_if_1) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{10,6,26}},
+ {?eh,tc_start,{ts_if_1_SUITE,init_per_suite}},
+ {?eh,tc_done,{ts_if_1_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc1}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc1,{skipped,
+ {failed,
+ {ts_if_1_SUITE,init_per_testcase,
+ {timetrap_timeout,2000}}}}}},
+ {?eh,test_stats,{0,0,{0,1}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc2}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc2,
+ {failed,{ts_if_1_SUITE,end_per_testcase,{timetrap_timeout,2000}}}}},
+ {?eh,test_stats,{1,0,{0,1}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc3}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc3,{failed,{timetrap_timeout,2000}}}},
+ {?eh,test_stats,{1,1,{0,1}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc4}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc4,{failed,{error,failed_on_purpose}}}},
+ {?eh,test_stats,{1,2,{0,1}}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc5,{skipped,{sequence_failed,seq1,tc4}}}},
+ {?eh,test_stats,{1,2,{1,1}}},
+
+ [{?eh,tc_start,{ts_if_1_SUITE,{init_per_group,seq2,[sequence]}}},
+ {?eh,tc_done,{ts_if_1_SUITE,{init_per_group,seq2,[sequence]},ok}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc4}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc4,{failed,{error,failed_on_purpose}}}},
+ {?eh,test_stats,{1,3,{1,1}}},
+ {?eh,tc_auto_skip,{ts_if_1_SUITE,tc5,{failed,{ts_if_1_SUITE,tc4}}}},
+ {?eh,test_stats,{1,3,{1,2}}},
+ {?eh,tc_start,{ts_if_1_SUITE,{end_per_group,seq2,[sequence]}}},
+ {?eh,tc_done,{ts_if_1_SUITE,{end_per_group,seq2,[sequence]},ok}}],
+
+ {?eh,tc_start,{ts_if_1_SUITE,tc6}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc6,{skipped,{require_failed,{not_available,void}}}}},
+ {?eh,test_stats,{1,3,{1,3}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc7}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc7,ok}},
+ {?eh,test_stats,{2,3,{1,3}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc8}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc8,{skipped,"tc8 skipped"}}},
+ {?eh,test_stats,{2,3,{2,3}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc9}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc9,{skipped,'tc9 skipped'}}},
+ {?eh,test_stats,{2,3,{3,3}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc10}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc10,{failed,{error,{function_clause,'_'}}}}},
+ {?eh,test_stats,{2,4,{3,3}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc11}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc11,
+ {skipped,{failed,{ts_if_1_SUITE,init_per_testcase,bad_return}}}}},
+ {?eh,test_stats,{2,4,{3,4}}},
+
+ [{?eh,tc_start,{ts_if_1_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_done,{ts_if_1_SUITE,{init_per_group,g1,[]},{skipped,g1_got_skipped}}},
+ {?eh,tc_auto_skip,{ts_if_1_SUITE,gtc1,g1_got_skipped}},
+ {?eh,test_stats,{2,4,{3,5}}},
+ {?eh,tc_auto_skip,{ts_if_1_SUITE,end_per_group,g1_got_skipped}}],
+
+ {parallel,
+ [{?eh,tc_start,{ts_if_1_SUITE,{init_per_group,g2,[parallel]}}},
+ {?eh,tc_done,{ts_if_1_SUITE,{init_per_group,g2,[parallel]},ok}},
+ [{?eh,tc_start,{ts_if_1_SUITE,{init_per_group,g3,[]}}},
+ {?eh,tc_done,{ts_if_1_SUITE,{init_per_group,g3,[]},{skipped,g3_got_skipped}}},
+ {?eh,tc_auto_skip,{ts_if_1_SUITE,gtc2,g3_got_skipped}},
+ {?eh,test_stats,{2,4,{3,6}}},
+ {?eh,tc_auto_skip,{ts_if_1_SUITE,end_per_group,g3_got_skipped}}],
+ {?eh,tc_start,{ts_if_1_SUITE,{end_per_group,g2,[parallel]}}},
+ {?eh,tc_done,{ts_if_1_SUITE,{end_per_group,g2,[parallel]},ok}}]},
+
+ {?eh,tc_start,{ts_if_1_SUITE,tc12}},
+ {?eh,tc_done,{undefined,undefined,{testcase_aborted,{abort_current_testcase,tc12},'_'}}},
+ {?eh,test_stats,{2,5,{3,6}}},
+ {?eh,tc_start,{ts_if_1_SUITE,tc13}},
+ {?eh,tc_done,{ts_if_1_SUITE,tc13,ok}},
+ {?eh,test_stats,{3,5,{3,6}}},
+ {?eh,tc_start,{ts_if_1_SUITE,end_per_suite}},
+ {?eh,tc_done,{ts_if_1_SUITE,end_per_suite,ok}},
+%%!
+ {?eh,tc_start,{ts_if_2_SUITE,init_per_suite}},
+ {?eh,tc_done,{ts_if_2_SUITE,init_per_suite,
+ {failed,{error,{suite0_failed,{exited,suite0_goes_boom}}}}}},
+ {?eh,tc_auto_skip,{ts_if_2_SUITE,my_test_case,
+ {failed,{error,{suite0_failed,{exited,suite0_goes_boom}}}}}},
+ {?eh,test_stats,{3,5,{3,7}}},
+ {?eh,tc_auto_skip,{ts_if_2_SUITE,end_per_suite,
+ {failed,{error,{suite0_failed,{exited,suite0_goes_boom}}}}}},
+
+ {?eh,tc_start,{ct_framework,error_in_suite}},
+ {?eh,test_stats,{3,6,{3,7}}},
+
+ {?eh,tc_start,{ct_framework,error_in_suite}},
+ {?eh,test_stats,{3,7,{3,7}}},
+
+ {?eh,tc_start,{ts_if_5_SUITE,init_per_suite}},
+ {?eh,tc_done,{ts_if_5_SUITE,init_per_suite,
+ {skipped,{require_failed_in_suite0,{not_available,undef_variable}}}}},
+ {?eh,tc_auto_skip,{ts_if_5_SUITE,my_test_case,
+ {require_failed_in_suite0,{not_available,undef_variable}}}},
+ {?eh,test_stats,{3,7,{3,8}}},
+ {?eh,tc_auto_skip,{ts_if_5_SUITE,end_per_suite,
+ {require_failed_in_suite0,{not_available,undef_variable}}}},
+
+ {?eh,tc_start,{ts_if_6_SUITE,tc1}},
+ {?eh,tc_done,{ts_if_6_SUITE,tc1,{failed,{error,{suite0_failed,{exited,suite0_byebye}}}}}},
+ {?eh,test_stats,{3,7,{4,8}}},
+
+ {?eh,tc_start,{ts_if_7_SUITE,tc1}},
+ {?eh,tc_done,{ts_if_7_SUITE,tc1,ok}},
+ {?eh,test_stats,{4,7,{4,8}}},
+
+ {?eh,tc_start,{ts_if_8_SUITE,tc1}},
+ {?eh,tc_done,{ts_if_8_SUITE,tc1,{failed,{error,failed_on_purpose}}}},
+ {?eh,test_stats,{4,8,{4,8}}},
+
+ {?eh,tc_user_skip,{skipped_by_spec_1_SUITE,all,"should be skipped"}},
+ {?eh,test_stats,{4,8,{5,8}}},
+
+ {?eh,tc_start,{skipped_by_spec_2_SUITE,init_per_suite}},
+ {?eh,tc_done,{skipped_by_spec_2_SUITE,init_per_suite,ok}},
+ {?eh,tc_user_skip,{skipped_by_spec_2_SUITE,tc1,"should be skipped"}},
+ {?eh,test_stats,{4,8,{6,8}}},
+ {?eh,tc_start,{skipped_by_spec_2_SUITE,end_per_suite}},
+ {?eh,tc_done,{skipped_by_spec_2_SUITE,end_per_suite,ok}},
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
+
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/skipped_by_spec_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/skipped_by_spec_1_SUITE.erl
new file mode 100644
index 0000000000..e77e304834
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/skipped_by_spec_1_SUITE.erl
@@ -0,0 +1,127 @@
+%%
+%% %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%
+%%
+-module(skipped_by_spec_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/skipped_by_spec_2_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/skipped_by_spec_2_SUITE.erl
new file mode 100644
index 0000000000..384182e778
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/skipped_by_spec_2_SUITE.erl
@@ -0,0 +1,127 @@
+%%
+%% %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%
+%%
+-module(skipped_by_spec_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
new file mode 100644
index 0000000000..8e90df21ce
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
@@ -0,0 +1,191 @@
+%%
+%% %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%
+%%
+-module(ts_if_1_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,2}}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(g1, _Config) ->
+ {skip,g1_got_skipped};
+init_per_group(g3, _Config) ->
+ {skip,g3_got_skipped};
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(tc1, Config) ->
+ timer:sleep(5000),
+ Config;
+init_per_testcase(tc8, _Config) ->
+ {skip,"tc8 skipped"};
+init_per_testcase(tc11, Config) ->
+ bad_format;
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(tc2, Config) ->
+ timer:sleep(5000);
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [{g1,[],[gtc1]},
+ {g2,[parallel],[{g3,[],[gtc2]}]},
+
+ {seq2,[sequence],[tc4,tc5]}].
+
+sequences() ->
+ [{seq1,[tc4,tc5]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1, tc2, tc3,
+ {sequence,seq1},
+ {group,seq2},
+ tc6, tc7,
+ tc8, tc9, tc10,
+ tc11,
+ {group,g1},
+ {group,g2},
+ tc12, tc13].
+
+tc1(_) ->
+ exit(should_have_been_skipped).
+
+tc2(_) ->
+ exit(should_have_been_skipped).
+
+tc3(_) ->
+ timer:sleep(5000).
+
+tc4(_) ->
+ exit(failed_on_purpose).
+
+tc5(_) ->
+ exit(should_have_been_skipped).
+
+tc6() ->
+ [{require,void}].
+tc6(_) ->
+ exit(should_have_been_skipped).
+
+tc7() ->
+ bad_format.
+tc7(_) ->
+ done.
+
+tc8(_) ->
+ exit(should_have_been_skipped).
+
+tc9(_) ->
+ {skip,'tc9 skipped'}.
+
+tc10(config) ->
+ done.
+
+tc11(_) ->
+ exit(should_have_been_skipped).
+
+
+gtc1(_) ->
+ exit(should_have_been_skipped).
+
+gtc2(_) ->
+ exit(should_have_been_skipped).
+
+tc12(_) ->
+ F = fun() -> ct:abort_current_testcase({abort_current_testcase,tc12}) end,
+ spawn(F),
+ timer:sleep(500),
+ exit(should_have_been_aborted).
+
+tc13(_) ->
+ success.
+
+
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_2_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_2_SUITE.erl
new file mode 100644
index 0000000000..386b4402e6
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_2_SUITE.erl
@@ -0,0 +1,127 @@
+%%
+%% %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%
+%%
+-module(ts_if_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ exit(suite0_goes_boom).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [my_test_case].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+my_test_case() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+my_test_case(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_3_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_3_SUITE.erl
new file mode 100644
index 0000000000..70191d31ed
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_3_SUITE.erl
@@ -0,0 +1,128 @@
+%%
+%% %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%
+%%
+-module(ts_if_3_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+%% No all/0!!
+%%all() ->
+%% [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+my_test_case() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+my_test_case(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_4_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_4_SUITE.erl
new file mode 100644
index 0000000000..4b566fea5d
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_4_SUITE.erl
@@ -0,0 +1,127 @@
+%%
+%% %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%
+%%
+-module(ts_if_4_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ bad_format.
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+my_test_case() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+my_test_case(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_5_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_5_SUITE.erl
new file mode 100644
index 0000000000..c7b6b054fb
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_5_SUITE.erl
@@ -0,0 +1,128 @@
+%%
+%% %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%
+%%
+-module(ts_if_5_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}},
+ {require,undef_variable}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [my_test_case].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+my_test_case() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+my_test_case(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_6_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_6_SUITE.erl
new file mode 100644
index 0000000000..43440386e6
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_6_SUITE.erl
@@ -0,0 +1,111 @@
+%%
+%% %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%
+%%
+-module(ts_if_6_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ exit(suite0_byebye).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+tc1() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Config0) ->
+%% ok | exit() | {skip,Reason} | {comment,Comment} |
+%% {save_config,Config1} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% Comment = term()
+%%--------------------------------------------------------------------
+tc1(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_7_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_7_SUITE.erl
new file mode 100644
index 0000000000..a2254848d0
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_7_SUITE.erl
@@ -0,0 +1,93 @@
+%%
+%% %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%
+%%
+-module(ts_if_7_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_group(GroupName, Config0) ->
+%% void() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1].
+
+tc1() ->
+ exit(tc1_byebye).
+
+tc1(_) ->
+ done.
+
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_8_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_8_SUITE.erl
new file mode 100644
index 0000000000..990669cd4c
--- /dev/null
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_8_SUITE.erl
@@ -0,0 +1,52 @@
+%%
+%% %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%
+%%
+-module(ts_if_8_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc1].
+
+tc1(_) ->
+ exit(failed_on_purpose).
+
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
new file mode 100644
index 0000000000..6148e3280e
--- /dev/null
+++ b/lib/common_test/test/ct_test_support.erl
@@ -0,0 +1,976 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-2009. 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 Test support functions
+%%%
+%%% <p>This is a support module for testing the Common Test Framework.</p>
+%%%
+-module(ct_test_support).
+
+-include("test_server.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-export([init_per_suite/1, init_per_suite/2, end_per_suite/1,
+ init_per_testcase/2, end_per_testcase/2, write_testspec/3,
+ run/4, get_opts/1, wait_for_ct_stop/1]).
+
+-export([handle_event/2, start_event_receiver/1, get_events/2,
+ verify_events/3, reformat/2, log_events/3]).
+
+-include_lib("kernel/include/file.hrl").
+
+%%%-----------------------------------------------------------------
+%%% init_per_suite/1
+
+init_per_suite(Config) ->
+ init_per_suite(Config, 50).
+
+init_per_suite(Config, Level) ->
+ case delete_old_logs(os:type(), Config) of
+ {'EXIT',DelLogsReason} ->
+ test_server:format(0, "Failed to delete old log directories: ~p~n",
+ [DelLogsReason]);
+ _ ->
+ ok
+ end,
+ [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ case slave:start(Host, ct, []) of
+ {error,Reason} ->
+ test_server:fail(Reason);
+ {ok,CTNode} ->
+ test_server:format(0, "Node ~p started~n", [CTNode]),
+ DataDir = ?config(data_dir, Config),
+ PrivDir = ?config(priv_dir, Config),
+
+ %% PrivDir as well as directory of Test Server suites
+ %% have to be in code path on Common Test node.
+ true = rpc:call(CTNode, code, add_patha, [PrivDir]),
+ [_ | Parts] = lists:reverse(filename:split(DataDir)),
+ TSDir = filename:join(lists:reverse(Parts)),
+ true = rpc:call(CTNode, code, add_patha, [TSDir]),
+ test_server:format(Level, "Dirs added to code path (on ~w):~n"
+ "~s~n~s~n", [CTNode,TSDir,PrivDir]),
+
+ TraceFile = filename:join(DataDir, "ct.trace"),
+ case file:read_file_info(TraceFile) of
+ {ok,_} ->
+ [{trace_level,0},
+ {ct_opts,[{ct_trace,TraceFile}]},
+ {ct_node,CTNode} | Config];
+ _ ->
+ [{trace_level,Level},
+ {ct_opts,[]},
+ {ct_node,CTNode} | Config]
+ end
+ end.
+
+%%%-----------------------------------------------------------------
+%%% end_per_suite/1
+
+end_per_suite(Config) ->
+ CTNode = ?config(ct_node, Config),
+ PrivDir = ?config(priv_dir, Config),
+ true = rpc:call(CTNode, code, del_path, [filename:join(PrivDir,"")]),
+ slave:stop(CTNode),
+ ok.
+
+%%%-----------------------------------------------------------------
+%%% init_per_testcase/2
+
+init_per_testcase(_TestCase, Config) ->
+ {_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
+ test_server:format("See Common Test logs here:\n"
+ "<a href=\"file://~s/all_runs.html\">~s/all_runs.html</a>",
+ [LogDir,LogDir]),
+ Config.
+
+%%%-----------------------------------------------------------------
+%%% end_per_testcase/2
+
+end_per_testcase(_TestCase, Config) ->
+ CTNode = ?config(ct_node, Config),
+ wait_for_ct_stop(CTNode),
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%%
+
+write_testspec(TestSpec, Dir, Name) ->
+ TSFile = filename:join(Dir, Name),
+ {ok,Dev} = file:open(TSFile, [write]),
+ [io:format(Dev, "~p.~n", [Entry]) || Entry <- TestSpec],
+ file:close(Dev),
+ io:format("Test specification written to: ~p~n", [TSFile]),
+ io:format(user, "Test specification written to: ~p~n", [TSFile]),
+ TSFile.
+
+
+%%%-----------------------------------------------------------------
+%%%
+
+get_opts(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ TempDir = case os:getenv("TMP") of
+ false ->
+ case os:getenv("TEMP") of
+ false ->
+ undefined;
+ Tmp ->
+ create_tmp_logdir(Tmp)
+ end;
+ Tmp ->
+ create_tmp_logdir(Tmp)
+ end,
+ LogDir =
+ case os:getenv("CT_USE_TMP_DIR") of
+ false ->
+ case os:type() of
+ {win32,_} ->
+ if TempDir == undefined -> PrivDir;
+ true -> TempDir
+ end;
+ _ ->
+ PrivDir
+ end;
+ _ ->
+ TempDir
+ end,
+ InitOpts = ?config(ct_opts, Config),
+ [{logdir,LogDir} | InitOpts].
+
+
+%%%-----------------------------------------------------------------
+%%%
+run(M, F, A, Config) ->
+ CTNode = ?config(ct_node, Config),
+ Level = ?config(trace_level, Config),
+ test_server:format(Level, "Calling ~w:~w(~p) on ~p~n",
+ [M, F, A, CTNode]),
+ rpc:call(CTNode, M, F, A).
+
+
+%%%-----------------------------------------------------------------
+%%% wait_for_ct_stop/1
+
+wait_for_ct_stop(CTNode) ->
+ %% Give CT at least 15 sec to stop (in case of bad make).
+ wait_for_ct_stop(5, CTNode).
+
+wait_for_ct_stop(0, CTNode) ->
+ test_server:format(0, "Giving up! Stopping ~p.", [CTNode]),
+ ok;
+wait_for_ct_stop(Retries, CTNode) ->
+ case rpc:call(CTNode, erlang, whereis, [ct_util_server]) of
+ undefined ->
+ ok;
+ Pid ->
+ test_server:format(0, "Waiting for CT (~p) to finish (~p)...",
+ [Pid,Retries]),
+ timer:sleep(5000),
+ wait_for_ct_stop(Retries-1, CTNode)
+ end.
+
+%%%-----------------------------------------------------------------
+%%% EVENT HANDLING
+
+handle_event(EH, Event) ->
+ event_receiver ! {self(),{event,EH,Event}},
+ receive {event_receiver,ok} -> ok end,
+ ok.
+
+start_event_receiver(Config) ->
+ CTNode = ?config(ct_node, Config),
+ spawn_link(CTNode, fun() -> er() end).
+
+get_events(_, Config) ->
+ CTNode = ?config(ct_node, Config),
+ {event_receiver,CTNode} ! {self(),get_events},
+ Events = receive {event_receiver,Evs} -> Evs end,
+ {event_receiver,CTNode} ! stop,
+ Events.
+
+er() ->
+ register(event_receiver, self()),
+ er_loop([]).
+
+er_loop(Evs) ->
+ receive
+ {From,{event,EH,Ev}} ->
+ From ! {event_receiver,ok},
+ er_loop([{EH,Ev} | Evs]);
+ {From,get_events} ->
+ From ! {event_receiver,lists:reverse(Evs)},
+ er_loop(Evs);
+ stop ->
+ ok
+ end.
+
+verify_events(TEvs, Evs, Config) ->
+ Node = ?config(ct_node, Config),
+ case catch verify_events1(TEvs, Evs, Node, Config) of
+ {'EXIT',Reason} ->
+ Reason;
+ _ ->
+ ok
+ end.
+
+verify_events1(TEvs = [TestEv | TestEvs], Evs = [_|Events], Node, Config) ->
+%% test_server:format("Next expected event: ~p~n", [TestEv]),
+ case catch locate(TestEv, Node, Evs, Config) of
+ nomatch ->
+ verify_events1(TEvs, Events, Node, Config);
+ {'EXIT',Reason} ->
+ test_server:format("Failed to find ~p in ~p~n"
+ "Reason: ~p~n", [TestEv,Evs,Reason]),
+ exit(Reason);
+ {Config1,Events1} ->
+ if is_list(TestEv) ->
+ ok;
+ element(1,TestEv) == parallel ; element(1,TestEv) == shuffle ->
+ ok;
+ true ->
+ test_server:format("Found ~p!", [TestEv])
+ end,
+ verify_events1(TestEvs, Events1, Node, Config1)
+ end;
+
+verify_events1([TestEv|_], [], _, _) ->
+ test_server:format("Failed to find ~p in the list of events!~n", [TestEv]),
+ exit({event_not_found,TestEv});
+
+verify_events1([], Evs, _, Config) ->
+ {Config,Evs}.
+
+%%%----------------------------------------------------------------------------
+%%% locate({TEHandler,TEName,TEData}, TENode, Events, Config) -> {Config1,Evs1}
+%%%
+%%% A group is represented as either:
+%%% {parallel,ListOfCasesAndGroups},
+%%% {shuffle,ListOfCasesAndGroups}, or
+%%% ListOfCasesAndGroups.
+%%%
+%%% The two first and two last events in a group *may* be tc_start and tc_done
+%%% for init_per_group and end_per_group.
+
+%% group (not parallel or shuffle)
+locate(TEvs, Node, Evs, Config) when is_list(TEvs) ->
+ case TEvs of
+ [InitStart = {TEH,tc_start,{M,{init_per_group,GroupName,Props}}},
+ InitDone = {TEH,tc_done,{M,{init_per_group,GroupName,Props},R}} | TEvs1] ->
+ case Evs of
+ [{TEH,#event{name=tc_start,
+ node=Node,
+ data={M,{init_per_group,GroupName,Props}}}},
+ {TEH,#event{name=tc_done,
+ node=Node,
+ data={M,{init_per_group,GroupName,Props},R}}} | Evs1] ->
+ test_server:format("Found ~p!", [InitStart]),
+ test_server:format("Found ~p!", [InitDone]),
+ verify_events1(TEvs1, Evs1, Node, Config);
+ _ ->
+ nomatch
+ end;
+ _ ->
+ verify_events1(TEvs, Evs, Node, Config)
+ end;
+
+%% Parallel events: Each test case in the group should be specified in a list
+%% with the tc_start, followed by the tc_done event. The order of the cases
+%% is irrelevant, but it must be checked that every test case exists and
+%% that tc_done comes after tc_start.
+locate({parallel,TEvs}, Node, Evs, Config) ->
+ Start =
+ case TEvs of
+ [InitStart = {TEH,tc_start,{M,{init_per_group,GroupName,Props}}},
+ InitDone = {TEH,tc_done,{M,{init_per_group,GroupName,Props},R}} | TEs] ->
+ case Evs of
+ [{TEH,#event{name=tc_start,
+ node=Node,
+ data={M,{init_per_group,GroupName,Props}}}},
+ {TEH,#event{name=tc_done,
+ node=Node,
+ data={M,{init_per_group,GroupName,Props},R}}} | Es] ->
+ test_server:format("Found ~p!", [InitStart]),
+ test_server:format("Found ~p!", [InitDone]),
+ {TEs,Es};
+ _ ->
+ nomatch
+ end;
+ _ ->
+ {TEvs,Evs}
+ end,
+ case Start of
+ nomatch ->
+ nomatch;
+ {TEvs1,Evs1} ->
+ {TcDoneEvs,RemainEvs,_} =
+ lists:foldl(
+ %% tc_start event for a parallel test case
+ fun(TEv={TEH,tc_start,{M,F}}, {Done,RemEvs,RemSize}) ->
+ %% drop events until TEv is found
+ Evs2 = lists:dropwhile(
+ fun({EH,#event{name=tc_start,
+ node=EvNode,
+ data={Mod,Func}}}) when
+ EH == TEH, EvNode == Node,
+ Mod == M, Func == F ->
+ false;
+ (_) ->
+ true
+ end, Evs1),
+ %% split the list at the tc_done event and record the smallest
+ %% list of remaining events (Evs) as possible
+ RemEvs1 =
+ lists:dropwhile(
+ fun({EH,#event{name=tc_done,
+ node=EvNode,
+ data={Mod,Func,_}}}) when
+ EH == TEH, EvNode == Node,
+ Mod == M, Func == F ->
+ false;
+ (_) ->
+ true
+ end, Evs2),
+ case RemEvs1 of
+ [] when Evs2 == [] ->
+ exit({unmatched,TEv});
+ [] ->
+ test_server:format("Found ~p!", [TEv]),
+ exit({tc_done_not_found,TEv});
+ [TcDone|Evs3] ->
+ test_server:format("Found ~p!", [TEv]),
+ RemSize1 = length(Evs3),
+ if RemSize1 < RemSize ->
+ {[TcDone|Done],Evs3,RemSize1};
+ true ->
+ {[TcDone|Done],RemEvs,RemSize}
+ end
+ end;
+ %% tc_done event for a parallel test case
+ (TEv={TEH,tc_done,{M,F,R}}, {Done,RemEvs,RemSize}) ->
+ case [E || E={EH,#event{name=tc_done,
+ node=EvNode,
+ data={Mod,Func,Result}}} <- Done,
+ EH == TEH, EvNode == Node, Mod == M,
+ Func == F, Result == R] of
+ [TcDone|_] ->
+ test_server:format("Found ~p!", [TEv]),
+ {lists:delete(TcDone, Done),RemEvs,RemSize};
+ [] ->
+ exit({unmatched,TEv})
+ end;
+ %% tc_start event for end_per_group
+ (TEv={TEH,tc_start,{M,{end_per_group,GroupName,Props}}},
+ {Done,RemEvs,_RemSize}) ->
+ RemEvs1 =
+ lists:dropwhile(
+ fun({EH,#event{name=tc_start,
+ node=EvNode,
+ data={Mod,{end_per_group,
+ EvGName,EvProps}}}}) when
+ EH == TEH, EvNode == Node, Mod == M,
+ EvGName == GroupName, EvProps == Props ->
+ false;
+ (_) ->
+ true
+ end, RemEvs),
+ case RemEvs1 of
+ [] ->
+ exit({end_per_group_not_found,TEv});
+ [_ | RemEvs2] ->
+ test_server:format("Found ~p!", [TEv]),
+ {Done,RemEvs2,length(RemEvs2)}
+ end;
+ %% tc_done event for end_per_group
+ (TEv={TEH,tc_done,{M,{end_per_group,GroupName,Props},R}},
+ {Done,RemEvs,_RemSize}) ->
+ RemEvs1 =
+ lists:dropwhile(
+ fun({EH,#event{name=tc_done,
+ node=EvNode,
+ data={Mod,{end_per_group,
+ EvGName,EvProps},Res}}}) when
+ EH == TEH, EvNode == Node, Mod == M,
+ EvGName == GroupName, EvProps == Props, Res == R ->
+ false;
+ (_) ->
+ true
+ end, RemEvs),
+ case RemEvs1 of
+ [] ->
+ exit({end_per_group_not_found,TEv});
+ [_ | RemEvs2] ->
+ test_server:format("Found ~p!", [TEv]),
+ {Done,RemEvs2,length(RemEvs2)}
+ end;
+ %% end_per_group auto skipped
+ (TEv={TEH,tc_auto_skip,{M,end_per_group,R}}, {Done,RemEvs,_RemSize}) ->
+ RemEvs1 =
+ lists:dropwhile(
+ fun({EH,#event{name=tc_auto_skip,
+ node=EvNode,
+ data={Mod,end_per_group,Reason}}}) when
+ EH == TEH, EvNode == Node, Mod == M, Reason == R ->
+ false;
+ (_) ->
+ true
+ end, RemEvs),
+ case RemEvs1 of
+ [] ->
+ exit({end_per_group_not_found,TEv});
+ [_AutoSkip | RemEvs2] ->
+ {Done,RemEvs2,length(RemEvs2)}
+ end;
+ %% match other event than test case
+ (TEv={TEH,N,D}, Acc) when D == '_' ->
+ case [E || E={EH,#event{name=Name,
+ node=EvNode,
+ data=_}} <- Evs1,
+ EH == TEH, EvNode == Node, Name == N] of
+ [] ->
+ exit({unmatched,TEv});
+ _ ->
+ test_server:format("Found ~p!", [TEv]),
+ Acc
+ end;
+ (TEv={TEH,N,D}, Acc) ->
+ case [E || E={EH,#event{name=Name,
+ node=EvNode,
+ data=Data}} <- Evs1,
+ EH == TEH, EvNode == Node, Name == N, Data == D] of
+ [] ->
+ exit({unmatched,TEv});
+ _ ->
+ test_server:format("Found ~p!", [TEv]),
+ Acc
+ end;
+ %% start of a sub-group
+ (SubGroupTEvs, Acc) when is_list(SubGroupTEvs) ->
+ verify_events1(SubGroupTEvs, Evs1, Node, Config),
+ Acc;
+ (TEv={Prop,_SubGroupTEvs}, Acc) when
+ Prop == shuffle ; Prop == parallel ->
+ verify_events1([TEv], Evs1, Node, Config),
+ Acc
+ end, {[],Evs1,length(Evs1)}, TEvs1),
+ case TcDoneEvs of
+ [] ->
+ test_server:format("Found all parallel events!", []),
+ {Config,RemainEvs};
+ _ ->
+ exit({unexpected_events,TcDoneEvs})
+ end
+ end;
+
+%% Shuffled events: Each test case in the group should be specified in a list
+%% with the tc_start, followed by the tc_done event. The order of the cases
+%% is irrelevant, but it must be checked that every test case exists and
+%% that the tc_done event follows the tc_start.
+locate({shuffle,TEvs}, Node, Evs, Config) ->
+ Start =
+ case TEvs of
+ [InitStart = {TEH,tc_start,{M,{init_per_group,GroupName,Props}}},
+ InitDone = {TEH,tc_done,{M,{init_per_group,GroupName,Props},R}} | TEs] ->
+ case Evs of
+ [{TEH,#event{name=tc_start,
+ node=Node,
+ data={M,{init_per_group,GroupName,EvProps}}}},
+ {TEH,#event{name=tc_done,
+ node=Node,
+ data={M,{init_per_group,GroupName,EvProps},R}}} | Es] ->
+ case proplists:get_value(shuffle, Props) of
+ '_' ->
+ case proplists:get_value(shuffle, EvProps) of
+ false ->
+ exit({no_shuffle_prop_found,{M,init_per_group,
+ GroupName,EvProps}});
+ _ ->
+ PropsCmp = proplists:delete(shuffle, EvProps),
+ PropsCmp = proplists:delete(shuffle, Props)
+ end;
+ _ ->
+ Props = EvProps
+ end,
+ test_server:format("Found ~p!", [InitStart]),
+ test_server:format("Found ~p!", [InitDone]),
+ {TEs,Es};
+ _ ->
+ nomatch
+ end;
+ _ ->
+ {TEvs,Evs}
+ end,
+ case Start of
+ nomatch ->
+ nomatch;
+ {TEvs1,Evs1} ->
+ {TcDoneEvs,RemainEvs,_} =
+ lists:foldl(
+ %% tc_start event for a test case
+ fun(TEv={TEH,tc_start,{M,F}}, {Done,RemEvs,RemSize}) ->
+ %% drop events until TEv is found
+ Evs2 = lists:dropwhile(
+ fun({EH,#event{name=tc_start,
+ node=EvNode,
+ data={Mod,Func}}}) when
+ EH == TEH, EvNode == Node,
+ Mod == M, Func == F ->
+ false;
+ (_) ->
+ true
+ end, Evs1),
+ %% verify the tc_done event comes next in Evs
+ case Evs2 of
+ [] ->
+ exit({unmatched,TEv});
+ [_TcStart, TcDone={TEH,#event{name=tc_done,
+ node=Node,
+ data={M,F,_}}} | Evs3] ->
+ test_server:format("Found ~p!", [TEv]),
+ RemSize1 = length(Evs3),
+ if RemSize1 < RemSize ->
+ {[TcDone|Done],Evs3,RemSize1};
+ true ->
+ {[TcDone|Done],RemEvs,RemSize}
+ end
+ end;
+ %% tc_done event for a test case
+ (TEv={TEH,tc_done,{M,F,R}}, {Done,RemEvs,RemSize}) ->
+ case [E || E={EH,#event{name=tc_done,
+ node=EvNode,
+ data={Mod,Func,Result}}} <- Done,
+ EH == TEH, EvNode == Node, Mod == M,
+ Func == F, Result == R] of
+ [TcDone|_] ->
+ test_server:format("Found ~p!", [TEv]),
+ {lists:delete(TcDone, Done),RemEvs,RemSize};
+ [] ->
+ exit({unmatched,TEv})
+ end;
+ %% tc_start event for end_per_group
+ (TEv={TEH,tc_start,{M,{end_per_group,GroupName,Props}}},
+ {Done,RemEvs,_RemSize}) ->
+ RemEvs1 =
+ lists:dropwhile(
+ fun({EH,#event{name=tc_start,
+ node=EvNode,
+ data={Mod,{end_per_group,
+ EvGName,_}}}}) when
+ EH == TEH, EvNode == Node, Mod == M,
+ EvGName == GroupName ->
+ false;
+ (_) ->
+ true
+ end, RemEvs),
+ case RemEvs1 of
+ [] ->
+ exit({end_per_group_not_found,TEv});
+ [{_,#event{data={_,{_,_,EvProps1}}}} | RemEvs2] ->
+ case proplists:get_value(shuffle, Props) of
+ '_' ->
+ case proplists:get_value(shuffle, EvProps1) of
+ false ->
+ exit({no_shuffle_prop_found,
+ {M,end_per_group,GroupName,EvProps1}});
+ _ ->
+ PropsCmp1 = proplists:delete(shuffle, EvProps1),
+ PropsCmp1 = proplists:delete(shuffle, Props)
+ end;
+ _ ->
+ Props = EvProps1
+ end,
+ test_server:format("Found ~p!", [TEv]),
+ {Done,RemEvs2,length(RemEvs2)}
+ end;
+ %% tc_done event for end_per_group
+ (TEv={TEH,tc_done,{M,{end_per_group,GroupName,Props},R}},
+ {Done,RemEvs,_RemSize}) ->
+ RemEvs1 =
+ lists:dropwhile(
+ fun({EH,#event{name=tc_done,
+ node=EvNode,
+ data={Mod,{end_per_group,
+ EvGName,_},Res}}}) when
+ EH == TEH, EvNode == Node, Mod == M,
+ EvGName == GroupName, Res == R ->
+ false;
+ (_) ->
+ true
+ end, RemEvs),
+ case RemEvs1 of
+ [] ->
+ exit({end_per_group_not_found,TEv});
+ [{_,#event{data={_,{_,_,EvProps1},_}}} | RemEvs2] ->
+ case proplists:get_value(shuffle, Props) of
+ '_' ->
+ case proplists:get_value(shuffle, EvProps1) of
+ false ->
+ exit({no_shuffle_prop_found,
+ {M,end_per_group,GroupName,EvProps1}});
+ _ ->
+ PropsCmp1 = proplists:delete(shuffle, EvProps1),
+ PropsCmp1 = proplists:delete(shuffle, Props)
+ end;
+ _ ->
+ Props = EvProps1
+ end,
+ test_server:format("Found ~p!", [TEv]),
+ {Done,RemEvs2,length(RemEvs2)}
+ end;
+ %% end_per_group auto skipped
+ (TEv={TEH,tc_auto_skip,{M,end_per_group,R}}, {Done,RemEvs,_RemSize}) ->
+ RemEvs1 =
+ lists:dropwhile(
+ fun({EH,#event{name=tc_auto_skip,
+ node=EvNode,
+ data={Mod,end_per_group,Reason}}}) when
+ EH == TEH, EvNode == Node, Mod == M, Reason == R ->
+ false;
+ (_) ->
+ true
+ end, RemEvs),
+ case RemEvs1 of
+ [] ->
+ exit({end_per_group_not_found,TEv});
+ [_AutoSkip | RemEvs2] ->
+ {Done,RemEvs2,length(RemEvs2)}
+ end;
+ %% match other event than test case
+ (TEv={TEH,N,D}, Acc) when D == '_' ->
+ case [E || E={EH,#event{name=Name,
+ node=EvNode,
+ data=_}} <- Evs1,
+ EH == TEH, EvNode == Node, Name == N] of
+ [] ->
+ exit({unmatched,TEv});
+ _ ->
+ test_server:format("Found ~p!", [TEv]),
+ Acc
+ end;
+ (TEv={TEH,N,D}, Acc) ->
+ case [E || E={EH,#event{name=Name,
+ node=EvNode,
+ data=Data}} <- Evs1,
+ EH == TEH, EvNode == Node, Name == N, Data == D] of
+ [] ->
+ exit({unmatched,TEv});
+ _ ->
+ test_server:format("Found ~p!", [TEv]),
+ Acc
+ end;
+ %% start of a sub-group
+ (SubGroupTEvs, Acc) when is_list(SubGroupTEvs) ->
+ verify_events1(SubGroupTEvs, Evs1, Node, Config),
+ Acc;
+ (TEv={Prop,_SubGroupTEvs}, Acc) when
+ Prop == shuffle ; Prop == parallel ->
+ verify_events1([TEv], Evs1, Node, Config),
+ Acc
+ end, {[],Evs1,length(Evs1)}, TEvs1),
+ case TcDoneEvs of
+ [] ->
+ test_server:format("Found all shuffled events!", []),
+ {Config,RemainEvs};
+ _ ->
+ exit({unexpected_events,TcDoneEvs})
+ end
+ end;
+
+locate({TEH,Name,{'DEF','RUNDIR'}}, Node, [Ev|Evs], Config) ->
+ case Ev of
+ {TEH,#event{name=Name, node=Node, data=EvData}} ->
+ {_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
+ D = filename:join(LogDir, "ct_run." ++ atom_to_list(Node)),
+ case string:str(EvData, D) of
+ 0 -> exit({badmatch,EvData});
+ _ -> ok
+ end,
+ {Config,Evs};
+ _ ->
+ nomatch
+ end;
+
+locate({TEH,Name,{'DEF',{'START_TIME','LOGDIR'}}}, Node, [Ev|Evs], Config) ->
+ case Ev of
+ {TEH,#event{name=Name, node=Node, data=EvData}} ->
+ case EvData of
+ {DT={{_,_,_},{_,_,_}},Dir} when is_list(Dir) ->
+ {_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
+ D = filename:join(LogDir, "ct_run." ++ atom_to_list(Node)),
+ case string:str(Dir, D) of
+ 0 -> exit({badmatch,Dir});
+ _ -> ok
+ end,
+ {[{start_time,DT}|Config],Evs};
+ Data ->
+ exit({badmatch,Data})
+ end;
+ _ ->
+ nomatch
+ end;
+
+locate({TEH,Name,{'DEF','STOP_TIME'}}, Node, [Ev|Evs], Config) ->
+ case Ev of
+ {TEH,#event{name=Name, node=Node, data=EvData}} ->
+ case EvData of
+ DT={{_,_,_},{_,_,_}} ->
+ {[{stop_time,DT}|Config],Evs};
+ Data ->
+ exit({badmatch,Data})
+ end;
+ _ ->
+ nomatch
+ end;
+
+%% to match variable data as a result of a failed test case
+locate({TEH,tc_done,{Mod,Func,{failed,{error,{Slogan,'_'}}}}}, Node, [Ev|Evs], Config) ->
+ case Ev of
+ {TEH,#event{name=tc_done, node=Node,
+ data={Mod,Func,{failed,{error,{Slogan,_}}}}}} ->
+ {Config,Evs};
+ _ ->
+ nomatch
+ end;
+
+%% to match variable data as a result of an aborted test case
+locate({TEH,tc_done,{undefined,undefined,{testcase_aborted,
+ {abort_current_testcase,Func},'_'}}},
+ Node, [Ev|Evs], Config) ->
+ case Ev of
+ {TEH,#event{name=tc_done, node=Node,
+ data={undefined,undefined,
+ {testcase_aborted,{abort_current_testcase,Func},_}}}} ->
+ {Config,Evs};
+ _ ->
+ nomatch
+ 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};
+ _ ->
+ 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.
+
+log_events(TC, Events, PrivDir) ->
+ LogFile = filename:join(PrivDir, atom_to_list(TC)++".events"),
+ {ok,Dev} = file:open(LogFile, [write]),
+ io:format(Dev, "[~n", []),
+ log_events1(Events, Dev, " "),
+ file:close(Dev),
+ io:format("Events written to logfile: ~p~n", [LogFile]),
+ io:format(user, "Events written to logfile: ~p~n", [LogFile]).
+
+log_events1(Evs, Dev, "") ->
+ log_events1(Evs, Dev, " ");
+log_events1([E={_EH,tc_start,{_M,{init_per_group,_GrName,Props}}} | Evs], Dev, Ind) ->
+ case get_prop(Props) of
+ undefined ->
+ io:format(Dev, "~s[~p,~n", [Ind,E]),
+ log_events1(Evs, Dev, Ind++" ");
+ Prop ->
+ io:format(Dev, "~s{~w,~n~s[~p,~n", [Ind,Prop,Ind++" ",E]),
+ log_events1(Evs, Dev, Ind++" ")
+ end;
+log_events1([E={_EH,tc_done,{_M,{init_per_group,_GrName,_Props},_R}} | Evs], Dev, Ind) ->
+ io:format(Dev, "~s~p,~n", [Ind,E]),
+ log_events1(Evs, Dev, Ind++" ");
+log_events1([E={_EH,tc_start,{_M,{end_per_group,_GrName,_Props}}} | Evs], Dev, Ind) ->
+ Ind1 = Ind -- " ",
+ io:format(Dev, "~s~p,~n", [Ind1,E]),
+ log_events1(Evs, Dev, Ind1);
+log_events1([E={_EH,tc_done,{_M,{end_per_group,_GrName,Props},_R}} | Evs], Dev, Ind) ->
+ case get_prop(Props) of
+ undefined ->
+ io:format(Dev, "~s~p],~n", [Ind,E]),
+ log_events1(Evs, Dev, Ind--" ");
+ _Prop ->
+ io:format(Dev, "~s~p]},~n", [Ind,E]),
+ log_events1(Evs, Dev, Ind--" ")
+ end;
+log_events1([E={_EH,tc_auto_skip,{_M,end_per_group,_Reason}} | Evs], Dev, Ind) ->
+ io:format(Dev, "~s~p],~n", [Ind,E]),
+ log_events1(Evs, Dev, Ind--" ");
+log_events1([E], Dev, Ind) ->
+ io:format(Dev, "~s~p~n].~n", [Ind,E]),
+ ok;
+log_events1([E | Evs], Dev, Ind) ->
+ io:format(Dev, "~s~p,~n", [Ind,E]),
+ log_events1(Evs, Dev, Ind);
+log_events1([], _Dev, _Ind) ->
+ ok.
+
+get_prop(Props) ->
+ case lists:member(parallel, Props) of
+ true -> parallel;
+ false -> case lists:member(shuffle, Props) of
+ true -> shuffle;
+ false -> case lists:keysearch(shuffle, 1, Props) of
+ {value,_} -> shuffle;
+ _ -> undefined
+ end
+ end
+ end.
+
+reformat([{_EH,#event{name=start_write_file,data=_}} | Events], EH) ->
+ reformat(Events, EH);
+reformat([{_EH,#event{name=finished_write_file,data=_}} | Events], EH) ->
+ reformat(Events, EH);
+reformat([{_EH,#event{name=start_make,data=_}} | Events], EH) ->
+ reformat(Events, EH);
+reformat([{_EH,#event{name=finished_make,data=_}} | Events], EH) ->
+ reformat(Events, EH);
+reformat([{_EH,#event{name=start_logging,data=_}} | Events], EH) ->
+ [{EH,start_logging,{'DEF','RUNDIR'}} | reformat(Events, EH)];
+reformat([{_EH,#event{name=test_start,data=_}} | Events], EH) ->
+ [{EH,test_start,{'DEF',{'START_TIME','LOGDIR'}}} | reformat(Events, EH)];
+reformat([{_EH,#event{name=test_done,data=_}} | Events], EH) ->
+ [{EH,test_done,{'DEF','STOP_TIME'}} | reformat(Events, EH)];
+reformat([{_EH,#event{name=test_stats,data=Data}} | Events], EH) ->
+ [{EH,test_stats,Data} | reformat(Events, EH)];
+%% use this to only print the last test_stats event:
+%% case [N || {_,#event{name=N}} <- Events, N == test_stats] of
+%% [] -> % last stats event
+%% [{EH,test_stats,Data} | reformat(Events, EH)];
+%% _ ->
+%% reformat(Events, EH)
+%% end;
+reformat([{_EH,#event{name=Name,data=Data}} | Events], EH) ->
+ [{EH,Name,Data} | reformat(Events, EH)];
+reformat([], _EH) ->
+ [].
+
+
+%%%-----------------------------------------------------------------
+%%% MISC HELP FUNCTIONS
+
+create_tmp_logdir(Tmp) ->
+ LogDir = filename:join(Tmp,"ct"),
+ file:make_dir(LogDir),
+ LogDir.
+
+delete_old_logs({win32,_}, Config) ->
+ case {?config(priv_dir, Config),?config(logdir, get_opts(Config))} of
+ {LogDir,LogDir} ->
+ ignore;
+ {_,LogDir} -> % using tmp for logs
+ catch delete_dirs(LogDir)
+ end;
+
+delete_old_logs(_, Config) ->
+ case os:getenv("CT_USE_TMP_DIR") of
+ false ->
+ ignore;
+ _ ->
+ catch delete_dirs(?config(logdir, get_opts(Config)))
+ end.
+
+delete_dirs(LogDir) ->
+ Now = calendar:datetime_to_gregorian_seconds(calendar:local_time()),
+ SaveTime = case os:getenv("CT_SAVE_OLD_LOGS") of
+ false ->
+ 28800;
+ SaveTime0 ->
+ list_to_integer(SaveTime0)
+ end,
+ Deadline = Now - SaveTime,
+ Dirs = filelib:wildcard(filename:join(LogDir,"ct_run*")),
+ Dirs2Del =
+ lists:foldl(fun(Dir, Del) ->
+ [S,Mi,H,D,Mo,Y|_] =
+ lists:reverse(string:tokens(Dir, [$.,$-,$_])),
+ S2I = fun(Str) -> list_to_integer(Str) end,
+ DT = {{S2I(Y),S2I(Mo),S2I(D)}, {S2I(H),S2I(Mi),S2I(S)}},
+ Then = calendar:datetime_to_gregorian_seconds(DT),
+ if Then > Deadline ->
+ Del;
+ true ->
+ [Dir | Del]
+ end
+ end, [], Dirs),
+ case length(Dirs2Del) of
+ 0 ->
+ test_server:format(0, "No log directories older than ~w secs.", [SaveTime]);
+ N ->
+ test_server:format(0, "Deleting ~w directories older than ~w secs.", [N,SaveTime])
+ end,
+ delete_dirs(LogDir, Dirs2Del).
+
+delete_dirs(_, []) ->
+ ok;
+delete_dirs(LogDir, [Dir | Dirs]) ->
+ test_server:format(0, "Removing old log directory: ~s", [Dir]),
+ case catch rm_rec(Dir) of
+ {_,Reason} ->
+ test_server:format(0, "Delete failed! (~p)", [Reason]);
+ ok ->
+ ok
+ end,
+ delete_dirs(LogDir, Dirs).
+
+rm_rec(Dir) ->
+ %% ensure we're removing the ct_run directory
+ case lists:reverse(filename:split(Dir)) of
+ [[$c,$t,$_,$r,$u,$n,$.|_]|_] ->
+ rm_dir(filename:absname(Dir));
+ _ ->
+ {error,{invalid_logdir,Dir}}
+ end.
+
+rm_dir(Dir) ->
+ case file:list_dir(Dir) of
+ {error,Errno} ->
+ exit({ls_failed,Dir,Errno});
+ {ok,Files} ->
+ rm_files([filename:join(Dir, F) || F <- Files]),
+ file:del_dir(Dir)
+ end.
+
+rm_files([F | Fs]) ->
+ Base = filename:basename(F),
+ if Base == "." ; Base == ".." ->
+ rm_files(Fs);
+ true ->
+ case file:read_file_info(F) of
+ {ok,#file_info{type=directory}} ->
+ rm_dir(F),
+ rm_files(Fs);
+ {ok,_Regular} ->
+ case file:delete(F) of
+ ok ->
+ rm_files(Fs);
+ {error,Errno} ->
+ exit({del_failed,F,Errno})
+ end
+ end
+ end;
+rm_files([]) ->
+ ok.
+
diff --git a/lib/common_test/test/ct_test_support_eh.erl b/lib/common_test/test/ct_test_support_eh.erl
new file mode 100644
index 0000000000..fd3ae18746
--- /dev/null
+++ b/lib/common_test/test/ct_test_support_eh.erl
@@ -0,0 +1,127 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009. 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 Event handler module
+%%%
+%%% <p>This is an event handler module used for testing that
+%%% Common Test generates events as expected.</p>
+%%%
+-module(ct_test_support_eh).
+
+-behaviour(gen_event).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+%% gen_event callbacks
+-export([init/1, handle_event/2, handle_call/2,
+ handle_info/2, terminate/2, code_change/3]).
+
+-record(state, {cbm=ct_test_support,
+ trace_level=50}).
+
+%%====================================================================
+%% gen_event callbacks
+%%====================================================================
+%%--------------------------------------------------------------------
+%% Function: init(Args) -> {ok, State}
+%% Description: Whenever a new event handler is added to an event manager,
+%% this function is called to initialize the event handler.
+%%--------------------------------------------------------------------
+init(Args) ->
+
+ S1 = case lists:keysearch(cbm, 1, Args) of
+ {_,{cbm,CBM}} ->
+ #state{cbm=CBM};
+ _ ->
+ #state{}
+ end,
+ S2 = case lists:keysearch(trace_level, 1, Args) of
+ {_,{trace_level,Level}} ->
+ S1#state{trace_level=Level};
+ _ ->
+ S1
+ end,
+ print(S2#state.trace_level, "Event Handler ~w started!~n", [?MODULE]),
+ {ok,S2}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_event(Event, State) -> {ok, State} |
+%% {swap_handler, Args1, State1, Mod2, Args2} |
+%% remove_handler
+%% Description:Whenever an event manager receives an event sent using
+%% gen_event:notify/2 or gen_event:sync_notify/2, this function is called for
+%% each installed event handler to handle the event.
+%%--------------------------------------------------------------------
+handle_event(Event, State=#state{cbm=CBM, trace_level=_Level}) ->
+ % print(_Level, "~p: ~p~n", [Event#event.name,Event#event.data]),
+ CBM:handle_event(?MODULE, Event),
+ {ok,State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_call(Request, State) -> {ok, Reply, State} |
+%% {swap_handler, Reply, Args1, State1,
+%% Mod2, Args2} |
+%% {remove_handler, Reply}
+%% Description: Whenever an event manager receives a request sent using
+%% gen_event:call/3,4, this function is called for the specified event
+%% handler to handle the request.
+%%--------------------------------------------------------------------
+handle_call(_Req, State) ->
+ Reply = ok,
+ {ok, Reply, State}.
+
+%%--------------------------------------------------------------------
+%% Function:
+%% handle_info(Info, State) -> {ok, State} |
+%% {swap_handler, Args1, State1, Mod2, Args2} |
+%% remove_handler
+%% Description: This function is called for each installed event handler when
+%% an event manager receives any other message than an event or a synchronous
+%% request (or a system message).
+%%--------------------------------------------------------------------
+handle_info(_Info, State) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%% Function: terminate(Reason, State) -> void()
+%% Description:Whenever an event handler is deleted from an event manager,
+%% this function is called. It should be the opposite of Module:init/1 and
+%% do any necessary cleaning up.
+%%--------------------------------------------------------------------
+terminate(_Reason, _State) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: code_change(OldVsn, State, Extra) -> {ok, NewState}
+%% Description: Convert process state when code is changed
+%%--------------------------------------------------------------------
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+
+print(Level, _Str, _Args) ->
+ test_server:format(Level, _Str,_Args).
+
+
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index 8b5d74016a..ee07350c55 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1,3 +1,3 @@
-COMMON_TEST_VSN = 1.4.6
+COMMON_TEST_VSN = 1.4.7
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index 99e24205ae..f918f47415 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1996-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(test_server).
@@ -760,6 +760,10 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment) ->
spawn_fw_call(undefined,undefined,Pid,testcase_aborted_or_killed,
unknown,self(),Comment),
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment);
+ {fw_error,{FwMod,FwFunc,FwError}} ->
+ spawn_fw_call(FwMod,FwFunc,Pid,{framework_error,FwError},
+ unknown,self(),Comment),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment);
_ ->
%% the testcase has terminated because of Reason (e.g. an exit
%% because a linked process failed)
@@ -859,6 +863,22 @@ spawn_fw_call(Mod,{end_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
"</font>"]}}
end,
spawn_link(FwCall);
+
+spawn_fw_call(FwMod,FwFunc,_Pid,{framework_error,FwError},_,SendTo,_Comment) ->
+ FwCall =
+ fun() ->
+ test_server_sup:framework_call(report, [framework_error,
+ {{FwMod,FwFunc},FwError}]),
+ Comment =
+ lists:flatten(
+ io_lib:format("<font color=\"red\">"
+ "WARNING! ~w:~w failed!</font>", [FwMod,FwFunc])),
+ %% finished, report back
+ SendTo ! {self(),fw_notify_done,
+ {died,{error,{FwMod,FwFunc,FwError}},{FwMod,FwFunc},[],Comment}}
+ end,
+ spawn_link(FwCall);
+
spawn_fw_call(Mod,Func,Pid,Error,Loc,SendTo,Comment) ->
FwCall =
fun() ->
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index 667d0cc051..4cb5863955 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 2002-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(test_server_ctrl).
diff --git a/lib/test_server/src/test_server_line.erl b/lib/test_server/src/test_server_line.erl
index 26ef3a3040..848a9c23dd 100644
--- a/lib/test_server/src/test_server_line.erl
+++ b/lib/test_server/src/test_server_line.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2004-2009. All Rights Reserved.
-%%
+%%
+%% 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%
%%
-module(test_server_line).
@@ -347,6 +347,10 @@ munge_expr({'fun',Line,{clauses,Clauses}}, Vars) ->
%% Only for Vsn=raw_abstract_v1
{MungedClauses,Vars2}=munge_clauses(Clauses, Vars, []),
{{'fun',Line,{clauses,MungedClauses}}, Vars2};
+munge_expr({bc,Line,Expr,LC}, Vars) ->
+ {MungedExpr, Vars2} = munge_expr(Expr, Vars),
+ {MungedLC, Vars3} = munge_lc(LC, Vars2, []),
+ {{bc,Line,MungedExpr,MungedLC}, Vars3};
munge_expr(Form, Vars) -> % var|char|integer|float|string|atom|nil|bin|eof
{Form, Vars}.
@@ -363,6 +367,9 @@ munge_exprs([], Vars, MungedExprs) ->
munge_lc([{generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->
{MungedExpr, Vars2} = munge_expr(Expr, Vars),
munge_lc(LC, Vars2, [{generate,Line,Pattern,MungedExpr}|MungedLC]);
+munge_lc([{b_generate,Line,Pattern,Expr}|LC], Vars, MungedLC) ->
+ {MungedExpr, Vars2} = munge_expr(Expr, Vars),
+ munge_lc(LC, Vars2, [{b_generate,Line,Pattern,MungedExpr}|MungedLC]);
munge_lc([Expr|LC], Vars, MungedLC) ->
{MungedExpr, Vars2} = munge_expr(Expr, Vars),
munge_lc(LC, Vars2, [MungedExpr|MungedLC]);
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl
index c665f185fd..89edb0f881 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/test_server/src/test_server_sup.erl
@@ -1,19 +1,19 @@
%%
%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 1998-2009. All Rights Reserved.
-%%
+%%
+%% Copyright Ericsson AB 1998-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%
%%
@@ -497,7 +497,18 @@ framework_call(Callback,Func,Args,DefaultReturn) ->
end,
case erlang:function_exported(Mod,Func,length(Args)) of
true ->
- apply(Mod,Func,Args);
+ EH = fun(Reason) -> exit({fw_error,{Mod,Func,Reason}}) end,
+ try apply(Mod,Func,Args) of
+ Result ->
+ Result
+ catch
+ exit:Why ->
+ EH(Why);
+ error:Why ->
+ EH({Why,erlang:get_stacktrace()});
+ throw:Why ->
+ EH(Why)
+ end;
false ->
DefaultReturn
end.
diff --git a/lib/test_server/test/Makefile b/lib/test_server/test/Makefile
new file mode 100644
index 0000000000..702d73f5af
--- /dev/null
+++ b/lib/test_server/test/Makefile
@@ -0,0 +1,95 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-2009. 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%
+#
+
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ test_server_SUITE \
+ test_server_line_SUITE \
+ test_server_skip_SUITE \
+ test_server_conf01_SUITE \
+ test_server_conf02_SUITE \
+ test_server_parallel01_SUITE \
+ test_server_shuffle01_SUITE
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+INSTALL_PROGS= $(TARGET_FILES)
+
+EMAKEFILE=Emakefile
+COVERFILE=test_server.cover
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/test_server_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+
+ERL_MAKE_FLAGS += -pa $(ERL_TOP)/lib/test_server/ebin
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+
+EBIN = .
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+.PHONY: make_emakefile
+
+make_emakefile:
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) \
+ '*_SUITE_make' > $(EMAKEFILE)
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
+ >> $(EMAKEFILE)
+
+tests debug opt: make_emakefile
+ cd ../src && $(MAKE) ../ebin/test_server_line.beam
+ erl $(ERL_MAKE_FLAGS) -make
+
+clean:
+ rm -f $(EMAKEFILE)
+ rm -f $(TARGET_FILES) $(GEN_FILES)
+ rm -f core
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+
+release_tests_spec: make_emakefile
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) $(EMAKEFILE) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
+ $(INSTALL_PROGRAM) test_server.spec $(RELSYSDIR)
+ chmod -f -R u+w $(RELSYSDIR)
+ @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/lib/test_server/test/test_server.cover b/lib/test_server/test/test_server.cover
new file mode 100644
index 0000000000..c2366db166
--- /dev/null
+++ b/lib/test_server/test/test_server.cover
@@ -0,0 +1,20 @@
+{exclude,[test_server,
+ test_server_ctrl,
+ ts_selftest]}.
+
+%% Using include list here because the test_server might not find
+%% lib_dir for test_server - and so it will not find which modules to
+%% compile.
+{include,[erl2html2,
+ test_server_node,
+ test_server_sup,
+ ts,
+ ts_autoconf_vxworks,
+ ts_autoconf_win32,
+ ts_erl_config,
+ ts_install,
+ ts_lib,
+ ts_make,
+ ts_run,
+ vxworks_client]}.
+
diff --git a/lib/test_server/test/test_server.spec b/lib/test_server/test/test_server.spec
new file mode 100644
index 0000000000..23b0b71963
--- /dev/null
+++ b/lib/test_server/test/test_server.spec
@@ -0,0 +1,2 @@
+{topcase, {dir, "../test_server_test"}}.
+{skip,{test_server_SUITE,skip_case7,"This case should be noted as `Skipped'"}}.
diff --git a/lib/test_server/test/test_server_SUITE.erl b/lib/test_server/test/test_server_SUITE.erl
new file mode 100644
index 0000000000..dfe1028d3a
--- /dev/null
+++ b/lib/test_server/test/test_server_SUITE.erl
@@ -0,0 +1,554 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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%
+%%
+
+%%%------------------------------------------------------------------
+%%% Test Server self test.
+%%%------------------------------------------------------------------
+-module(test_server_SUITE).
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("test_server/include/test_server_line.hrl").
+-include_lib("kernel/include/file.hrl").
+-export([all/1]).
+
+-export([init_per_suite/1, end_per_suite/1]).
+-export([init_per_testcase/2, end_per_testcase/2, fin_per_testcase/2]).
+-export([config/1, comment/1, timetrap/1, timetrap_cancel/1, multiply_timetrap/1,
+ init_per_s/1, init_per_tc/1, end_per_tc/1,
+ timeconv/1, msgs/1, capture/1, timecall/1,
+ do_times/1, do_times_mfa/1, do_times_fun/1,
+ skip_cases/1, skip_case1/1, skip_case2/1, skip_case3/1,
+ skip_case4/1, skip_case5/1, skip_case6/1, skip_case7/1,
+ skip_case8/1, skip_case9/1, undefined_functions/1,
+ conf_init/1, check_new_conf/1, conf_cleanup/1,
+ check_old_conf/1, conf_init_fail/1, start_stop_node/1,
+ cleanup_nodes_init/1, check_survive_nodes/1, cleanup_nodes_fin/1,
+ commercial/1]).
+
+-export([dummy_function/0,dummy_function/1,doer/1]).
+
+all(doc) -> ["Test Server self test"];
+all(suite) ->
+ [config, comment, timetrap, timetrap_cancel, multiply_timetrap,
+ init_per_s, init_per_tc, end_per_tc,
+ timeconv, msgs, capture, timecall, do_times, skip_cases,
+ undefined_functions, commercial,
+ {conf, conf_init, [check_new_conf], conf_cleanup},
+ check_old_conf,
+ {conf, conf_init_fail,[conf_member_skip],conf_cleanup_skip},
+ start_stop_node,
+ {conf, cleanup_nodes_init,[check_survive_nodes],cleanup_nodes_fin},
+ config
+ ].
+
+
+init_per_suite(Config) ->
+ [{init_per_suite_var,ok}|Config].
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
+ Dog = ?t:timetrap(?t:minutes(2)),
+ Config1 = [{watchdog, Dog}|Config],
+ case Func of
+ init_per_tc ->
+ [{strange_var, 1}|Config1];
+ skip_case8 ->
+ {skipped, "This case should be noted as `Skipped'"};
+ skip_case9 ->
+ {skip, "This case should be noted as `Skipped'"};
+ _ ->
+ Config1
+ end;
+init_per_testcase(Func, Config) ->
+ io:format("Func:~p",[Func]),
+ io:format("Config:~p",[Config]),
+ ?t:fail("Arguments to init_per_testcase not correct").
+
+end_per_testcase(Func, Config) when is_atom(Func), is_list(Config) ->
+ Dog=?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ case Func of
+ end_per_tc -> io:format("CLEANUP => this test case is ok\n");
+ _Other -> ok
+ end;
+end_per_testcase(Func, Config) ->
+ io:format("Func:~p",[Func]),
+ io:format("Config:~p",[Config]),
+ ?t:fail("Arguments to end_per_testcase not correct").
+
+fin_per_testcase(Func, Config) ->
+ io:format("Func:~p",[Func]),
+ io:format("Config:~p",[Config]),
+ ?t:fail("fin_per_testcase/2 called, should have called end_per_testcase/2").
+
+
+config(suite) -> [];
+config(doc) -> ["Test that the Config variable is decent, ",
+ "and that the std config variables are correct ",
+ "(check that data/priv dir exists)."
+ "Also check that ?config macro works."];
+config(Config) when is_list(Config) ->
+ is_tuplelist(Config),
+ {value,{data_dir,Dd}}=lists:keysearch(data_dir,1,Config),
+ {value,{priv_dir,Dp}}=lists:keysearch(priv_dir,1,Config),
+ true=is_dir(Dd),
+ {ok, _Bin}=file:read_file(filename:join(Dd, "dummy_file")),
+ true=is_dir(Dp),
+
+ Dd = ?config(data_dir,Config),
+ Dp = ?config(priv_dir,Config),
+ ok;
+config(_Config) ->
+ ?t:fail("Config variable is not a list.").
+
+is_tuplelist([]) ->
+ true;
+is_tuplelist([{_A,_B}|Rest]) ->
+ is_tuplelist(Rest);
+is_tuplelist(_) ->
+ false.
+
+is_dir(Dir) ->
+ case file:read_file_info(Dir) of
+ {ok, #file_info{type=directory}} ->
+ true;
+ _ ->
+ false
+ end.
+
+comment(suite) -> [];
+comment(doc) -> ["Print a comment in the HTML log"];
+comment(Config) when is_list(Config) ->
+ ?t:comment("This comment should not occur in the HTML log because a later"
+ " comment shall overwrite it"),
+ ?t:comment("This comment is printed with the comment/1 function."
+ " It should occur in the HTML log").
+
+
+
+timetrap(suite) -> [];
+timetrap(doc) -> ["Test that timetrap works."];
+timetrap(Config) when is_list(Config) ->
+ TrapAfter = 3000,
+ Dog=?t:timetrap(TrapAfter),
+ process_flag(trap_exit, true),
+ TimeOut = TrapAfter * test_server:timetrap_scale_factor() + 1000,
+ receive
+ {'EXIT', Dog, {timetrap_timeout, _, _}} ->
+ ok;
+ {'EXIT', _OtherPid, {timetrap_timeout, _, _}} ->
+ ?t:fail("EXIT signal from wrong process")
+ after
+ TimeOut ->
+ ?t:fail("Timetrap is not working.")
+ end,
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+
+timetrap_cancel(suite) -> [];
+timetrap_cancel(doc) -> ["Test that timetrap_cancel works."];
+timetrap_cancel(Config) when is_list(Config) ->
+ Dog=?t:timetrap(1000),
+ receive
+ after
+ 500 ->
+ ok
+ end,
+ ?t:timetrap_cancel(Dog),
+ receive
+ after 1000 ->
+ ok
+ end,
+ ok.
+
+multiply_timetrap(suite) -> [];
+multiply_timetrap(doc) -> ["Test multiply timetrap"];
+multiply_timetrap(Config) when is_list(Config) ->
+ %% This simulates the call to test_server_ctrl:multiply_timetraps/1:
+ put(test_server_multiply_timetraps,2),
+
+ Dog = ?t:timetrap(500),
+ timer:sleep(800),
+ ?t:timetrap_cancel(Dog),
+
+ %% Reset
+ put(test_server_multiply_timetraps,1),
+ ok.
+
+
+init_per_s(suite) -> [];
+init_per_s(doc) -> ["Test that a Config that is altered in ",
+ "init_per_suite gets through to the testcases."];
+init_per_s(Config) ->
+ %% Check that the config var sent from init_per_suite
+ %% really exists.
+ {value, {init_per_suite_var, ok}} =
+ lists:keysearch(init_per_suite_var,1,Config),
+
+ %% Check that the other variables still exist.
+ {value,{data_dir,_Dd}}=lists:keysearch(data_dir,1,Config),
+ {value,{priv_dir,_Dp}}=lists:keysearch(priv_dir,1,Config),
+ ok.
+
+init_per_tc(suite) -> [];
+init_per_tc(doc) -> ["Test that a Config that is altered in ",
+ "init_per_testcase gets through to the ",
+ "actual testcase."];
+init_per_tc(Config) ->
+ %% Check that the config var sent from init_per_testcase
+ %% really exists.
+ {value, {strange_var, 1}} = lists:keysearch(strange_var,1,Config),
+
+ %% Check that the other variables still exist.
+ {value,{data_dir,_Dd}}=lists:keysearch(data_dir,1,Config),
+ {value,{priv_dir,_Dp}}=lists:keysearch(priv_dir,1,Config),
+ ok.
+
+end_per_tc(suite) -> [];
+end_per_tc(doc) -> ["Test that end_per_testcase/2 is called even if"
+ " test case fails"];
+end_per_tc(Config) when is_list(Config) ->
+ ?t:fail("This case should fail! Check that \"CLEANUP\" is"
+ " printed in the minor log file.").
+
+
+timeconv(suite) -> [];
+timeconv(doc) -> ["Test that the time unit conversion functions ",
+ "works."];
+timeconv(Config) when is_list(Config) ->
+ Val=2,
+ Secs=Val*1000,
+ Mins=Secs*60,
+ Hrs=Mins*60,
+ Secs=?t:seconds(2),
+ Mins=?t:minutes(2),
+ Hrs=?t:hours(2),
+ ok.
+
+
+msgs(suite) -> [];
+msgs(doc) -> ["Tests the messages_get function."];
+msgs(Config) when is_list(Config) ->
+ self() ! {hej, du},
+ self() ! {lite, "data"},
+ self() ! en_atom,
+ [{hej, du}, {lite, "data"}, en_atom] = ?t:messages_get(),
+ ok.
+
+capture(suite) -> [];
+capture(doc) -> ["Test that the capture functions work properly."];
+capture(Config) when is_list(Config) ->
+ String1="abcedfghjiklmnopqrstuvwxyz",
+ String2="0123456789",
+ ?t:capture_start(),
+ io:format(String1),
+ [String1]=?t:capture_get(),
+ io:format(String2),
+ [String2]=?t:capture_get(),
+ ?t:capture_stop(),
+ []=?t:capture_get(),
+ io:format(String2),
+ []=?t:capture_get(),
+ ok.
+
+timecall(suite) -> [];
+timecall(doc) -> ["Tests that timed calls work."];
+timecall(Config) when is_list(Config) ->
+ {_Time1, liten_apa_e_oxo_farlig} = ?t:timecall(?MODULE, dummy_function, []),
+ {Time2, jag_ar_en_gorilla} = ?t:timecall(?MODULE, dummy_function, [gorilla]),
+ DTime=round(Time2),
+ if
+ DTime<1 ->
+ ?t:fail("Timecall reported a too low time.");
+ DTime==1 ->
+ ok;
+ DTime>1 ->
+ ?t:fail("Timecall reported a too high time.")
+ end,
+ ok.
+
+dummy_function() ->
+ liten_apa_e_oxo_farlig.
+dummy_function(gorilla) ->
+ receive after 1000 -> ok end,
+ jag_ar_en_gorilla.
+
+
+do_times(suite) -> [do_times_mfa, do_times_fun];
+do_times(doc) -> ["Test the do_times function."].
+
+do_times_mfa(suite) -> [];
+do_times_mfa(doc) -> ["Test the do_times function with M,F,A given."];
+do_times_mfa(Config) when is_list(Config) ->
+ ?t:do_times(100, ?MODULE, doer, [self()]),
+ 100=length(?t:messages_get()),
+ ok.
+
+do_times_fun(suite) -> [];
+do_times_fun(doc) -> ["Test the do_times function with fun given."];
+do_times_fun(Config) when is_list(Config) ->
+ Self = self(),
+ ?t:do_times(100, fun() -> doer(Self) end),
+ 100=length(?t:messages_get()),
+ ok.
+
+doer(From) ->
+ From ! a,
+ ok.
+
+skip_cases(doc) -> ["Test all possible ways to skip a test case."];
+skip_cases(suite) -> [skip_case1, skip_case2, skip_case3, skip_case4,
+ skip_case5, skip_case6, skip_case7, skip_case8,
+ skip_case9].
+
+skip_case1(suite) -> [];
+skip_case1(doc) -> ["Test that you can return {skipped, Reason},"
+ " and that Reason is in the comment field in the HTML log"];
+skip_case1(Config) when is_list(Config) ->
+ %% If this comment shows, the case failed!!
+ ?t:comment("ERROR: This case should have been noted as `Skipped'"),
+ %% The Reason in {skipped, Reason} should overwrite a 'comment'
+ {skipped, "This case should be noted as `Skipped'"}.
+
+skip_case2(suite) -> [];
+skip_case2(doc) -> ["Test that you can return {skipped, Reason},"
+ " and that Reason is in the comment field in the HTML log"];
+skip_case2(Config) when is_list(Config) ->
+ %% If this comment shows, the case failed!!
+ ?t:comment("ERROR: This case should have been noted as `Skipped'"),
+ %% The Reason in {skipped, Reason} should overwrite a 'comment'
+ exit({skipped, "This case should be noted as `Skipped'"}).
+
+skip_case3(suite) -> [];
+skip_case3(doc) -> ["Test that you can return {skip, Reason},"
+ " and that Reason is in the comment field in the HTML log"];
+skip_case3(Config) when is_list(Config) ->
+ %% If this comment shows, the case failed!!
+ ?t:comment("ERROR: This case should have been noted as `Skipped'"),
+ %% The Reason in {skip, Reason} should overwrite a 'comment'
+ {skip, "This case should be noted as `Skipped'"}.
+
+skip_case4(suite) -> [];
+skip_case4(doc) -> ["Test that you can return {skip, Reason},"
+ " and that Reason is in the comment field in the HTML log"];
+skip_case4(Config) when is_list(Config) ->
+ %% If this comment shows, the case failed!!
+ ?t:comment("ERROR: This case should have been noted as `Skipped'"),
+ %% The Reason in {skip, Reason} should overwrite a 'comment'
+ exit({skip, "This case should be noted as `Skipped'"}).
+
+skip_case5(suite) -> {skipped, "This case should be noted as `Skipped'"};
+skip_case5(doc) -> ["Test that you can return {skipped, Reason}"
+ " from the specification clause"].
+
+skip_case6(suite) -> {skip, "This case should be noted as `Skipped'"};
+skip_case6(doc) -> ["Test that you can return {skip, Reason}"
+ " from the specification clause"].
+
+skip_case7(suite) -> [];
+skip_case7(doc) -> ["Test that skip works from a test specification file"];
+skip_case7(Config) when is_list(Config) ->
+ %% This case shall be skipped by adding
+ %% {skip, {test_server_SUITE, skip_case7, Reason}}.
+ %% to the test specification file.
+ ?t:fail("This case should have been Skipped by the .spec file").
+
+skip_case8(suite) -> [];
+skip_case8(doc) -> ["Test that {skipped, Reason} works from"
+ " init_per_testcase/2"];
+skip_case8(Config) when is_list(Config) ->
+ %% This case shall be skipped by adding a specific clause to
+ %% returning {skipped, Reason} from init_per_testcase/2 for this case.
+ ?t:fail("This case should have been Skipped by init_per_testcase/2").
+
+skip_case9(suite) -> [];
+skip_case9(doc) -> ["Test that {skip, Reason} works from a init_per_testcase/2"];
+skip_case9(Config) when is_list(Config) ->
+ %% This case shall be skipped by adding a specific clause to
+ %% returning {skip, Reason} from init_per_testcase/2 for this case.
+ ?t:fail("This case should have been Skipped by init_per_testcase/2").
+
+undefined_functions(suite) -> [];
+undefined_functions(doc) -> ["Check for calls to undefined functions in"
+ " test_server."
+ "Skip if cover is running"];
+undefined_functions(Config) when is_list(Config) ->
+ case whereis(cover_server) of
+ Pid when is_pid(Pid) ->
+ {skip,"Cover is running"};
+ undefined ->
+ undefined_functions()
+ end.
+
+undefined_functions() ->
+ TestServerDir = filename:dirname(code:which(test_server)),
+ Res = xref:d(TestServerDir),
+
+ {value,{unused,Unused}} = lists:keysearch(unused, 1, Res),
+ case Unused of
+ [] -> ok;
+ _ ->
+ lists:foreach(fun (MFA) ->
+ io:format("~s unused", [format_mfa(MFA)])
+ end, Unused)
+ end,
+
+ {value,{undefined,Undef0}} = lists:keysearch(undefined, 1, Res),
+ Undef = [U || U <- Undef0, not unresolved(U)],
+ case Undef of
+ [] -> ok;
+ _ ->
+ lists:foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls undefined ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, Undef),
+ ?t:fail({length(Undef),undefined_functions_in_otp})
+ end,
+ ok.
+
+unresolved({_,{_,'$F_EXPR',_}}) -> true;
+unresolved(_) -> false.
+
+format_mfa({M,F,A}) ->
+ lists:flatten(io_lib:format("~s:~s/~p", [M,F,A])).
+
+conf_init(doc) -> ["Test successful conf case: Change Config parameter"];
+conf_init(Config) when is_list(Config) ->
+ [{conf_init_var,1389}|Config].
+
+check_new_conf(suite) -> [];
+check_new_conf(doc) -> ["Check that Config parameter changed by"
+ " conf_init is used"];
+check_new_conf(Config) when is_list(Config) ->
+ 1389 = ?config(conf_init_var,Config),
+ ok.
+
+conf_cleanup(doc) -> ["Test successful conf case: Restore Config parameter"];
+conf_cleanup(Config) when is_list(Config) ->
+ lists:keydelete(conf_init_var,1,Config).
+
+check_old_conf(suite) -> [];
+check_old_conf(doc) -> ["Test that the restored Config is used after a"
+ " conf cleanup"];
+check_old_conf(Config) when is_list(Config) ->
+ undefined = ?config(conf_init_var,Config),
+ ok.
+
+conf_init_fail(doc) -> ["Test that config members are skipped if"
+ " conf init function fails."];
+conf_init_fail(Config) when is_list(Config) ->
+ ?t:fail("This case should fail! Check that conf_member_skip and"
+ " conf_cleanup_skip are skipped.").
+
+
+
+start_stop_node(suite) -> [];
+start_stop_node(doc) -> ["Test start and stop of slave and peer nodes"];
+start_stop_node(Config) when is_list(Config) ->
+ {ok,Node2} = ?t:start_node(node2,peer,[]),
+ {error, _} = ?t:start_node(node2,peer,[{fail_on_error,false}]),
+ true = lists:member(Node2,nodes()),
+
+ {ok,Node3} = ?t:start_node(node3,slave,[]),
+ {error, _} = ?t:start_node(node3,slave,[]),
+ true = lists:member(Node3,nodes()),
+
+ {ok,Node4} = ?t:start_node(node4,peer,[{wait,false}]),
+ case lists:member(Node4,nodes()) of
+ true ->
+ ?t:comment("WARNING: Node started with {wait,false}"
+ " is up faster than expected...");
+ false ->
+ wait_for_node(Node4,0),
+ true = lists:member(Node4,nodes())
+ end,
+
+ true = ?t:stop_node(Node2),
+ false = lists:member(Node2,nodes()),
+
+ true = ?t:stop_node(Node3),
+ false = lists:member(Node3,nodes()),
+
+ true = ?t:stop_node(Node4),
+ false = lists:member(Node4,nodes()),
+ timer:sleep(2000),
+ false = ?t:stop_node(Node4),
+
+ ok.
+
+
+wait_for_node(Node,Acc) ->
+ case net_adm:ping(Node) of
+ pang ->
+ timer:sleep(100),
+ wait_for_node(Node,Acc+100);
+ pong ->
+ Acc
+ end.
+
+cleanup_nodes_init(doc) -> ["Test that nodes are terminated when test case"
+ " is finished unless {cleanup,false} is given."];
+cleanup_nodes_init(Config) when is_list(Config) ->
+ {ok,DieSlave} = ?t:start_node(die_slave, slave, []),
+ {ok,SurviveSlave} = ?t:start_node(survive_slave, slave, [{cleanup,false}]),
+ {ok,DiePeer} = ?t:start_node(die_peer, peer, []),
+ {ok,SurvivePeer} = ?t:start_node(survive_peer, peer, [{cleanup,false}]),
+ [{die_slave,DieSlave},
+ {survive_slave,SurviveSlave},
+ {die_peer,DiePeer},
+ {survive_peer,SurvivePeer} | Config].
+
+
+
+check_survive_nodes(suite) -> [];
+check_survive_nodes(doc) -> ["Test that nodes with {cleanup,false} survived"];
+check_survive_nodes(Config) when is_list(Config) ->
+ timer:sleep(1000),
+ false = lists:member(?config(die_slave,Config),nodes()),
+ true = lists:member(?config(survive_slave,Config),nodes()),
+ false = lists:member(?config(die_peer,Config),nodes()),
+ true = lists:member(?config(survive_peer,Config),nodes()),
+ ok.
+
+
+cleanup_nodes_fin(doc) -> ["Test that nodes started with {cleanup,false}"
+ " can be stopped"];
+cleanup_nodes_fin(Config) when is_list(Config) ->
+ Slave = ?config(survive_slave,Config),
+ Peer = ?config(survive_peer,Config),
+
+ true = ?t:stop_node(Slave),
+ false = lists:member(Slave,nodes()),
+ true = ?t:stop_node(Peer),
+ false = lists:member(Peer,nodes()),
+
+ C1 = lists:keydelete(die_slave,1,Config),
+ C2 = lists:keydelete(survive_slave,1,C1),
+ C3 = lists:keydelete(die_peer,1,C2),
+ lists:keydelete(survive_peer,1,C3).
+
+commercial(Config) when is_list(Config) ->
+ case ?t:is_commercial() of
+ false -> {comment,"Open-source build"};
+ true -> {comment,"Commercial build"}
+ end.
+
+
diff --git a/lib/test_server/test/test_server_SUITE_data/dummy_file b/lib/test_server/test/test_server_SUITE_data/dummy_file
new file mode 100644
index 0000000000..65c88fbd75
--- /dev/null
+++ b/lib/test_server/test/test_server_SUITE_data/dummy_file
@@ -0,0 +1 @@
+Dummy file. \ No newline at end of file
diff --git a/lib/test_server/test/test_server_conf01_SUITE.erl b/lib/test_server/test/test_server_conf01_SUITE.erl
new file mode 100644
index 0000000000..a6d7dfe851
--- /dev/null
+++ b/lib/test_server/test/test_server_conf01_SUITE.erl
@@ -0,0 +1,187 @@
+%%
+%% %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%
+%%
+
+%%%------------------------------------------------------------------
+%%% Test Server self test.
+%%%------------------------------------------------------------------
+-module(test_server_conf01_SUITE).
+-include_lib("test_server/include/test_server.hrl").
+
+-compile(export_all).
+
+all(doc) -> ["Test simple conf case structure, with and without nested cases"];
+all(suite) ->
+ [
+ {conf, conf1_init, [conf1_tc1, conf1_tc2], conf1_end},
+
+ {conf, [], conf2_init, [conf2_tc1, conf2_tc2], conf2_end},
+
+ {conf, conf3_init, [conf3_tc1,
+
+ {conf, [], conf4_init, [conf4_tc1, conf4_tc2], conf4_end},
+
+ conf3_tc2], conf3_end},
+
+ conf5
+ ].
+
+%%---------- conf cases ----------
+
+conf1_init(Config) when is_list(Config) ->
+ [{cc1,conf1}|Config].
+conf1_end(_Config) ->
+ ok.
+
+conf2_init(Config) when is_list(Config) ->
+ [{cc2,conf2}|Config].
+conf2_end(_Config) ->
+ ok.
+
+conf3_init(Config) when is_list(Config) ->
+ [{cc3,conf3}|Config].
+conf3_end(_Config) ->
+ ok.
+
+conf4_init(Config) when is_list(Config) ->
+ [{cc4,conf4}|Config].
+conf4_end(_Config) ->
+ ok.
+
+conf5_init(Config) when is_list(Config) ->
+ [{cc5,conf5}|Config].
+conf5_end(_Config) ->
+ ok.
+
+conf6_init(Config) when is_list(Config) ->
+ [{cc6,conf6}|Config].
+conf6_end(_Config) ->
+ ok.
+
+
+conf5(suite) -> % test specification
+ [{conf, conf5_init, [conf5_tc1,
+
+ {conf, [], conf6_init, [conf6_tc1, conf6_tc2], conf6_end},
+
+ conf5_tc2], conf5_end}].
+
+
+%%---------- test cases ----------
+
+conf1_tc1(Config) when is_list(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ conf1 = ?config(cc1,Config),
+ ok.
+conf1_tc2(Config) when is_list(Config) ->
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf1 = ?config(cc1,Config),
+ ok.
+
+conf2_tc1(Config) when is_list(Config) ->
+ undefined = ?config(cc1,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ conf2 = ?config(cc2,Config),
+ ok.
+conf2_tc2(Config) when is_list(Config) ->
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf2 = ?config(cc2,Config),
+ ok.
+
+conf3_tc1(Config) when is_list(Config) ->
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ conf3 = ?config(cc3,Config),
+ ok.
+conf3_tc2(Config) when is_list(Config) ->
+ conf3 = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ ok.
+
+conf4_tc1(Config) when is_list(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ conf3 = ?config(cc3,Config),
+ conf4 = ?config(cc4,Config),
+ ok.
+conf4_tc2(Config) when is_list(Config) ->
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf3 = ?config(cc3,Config),
+ conf4 = ?config(cc4,Config),
+ ok.
+
+conf5_tc1(Config) when is_list(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf5 = ?config(cc5,Config),
+ ok.
+conf5_tc2(Config) when is_list(Config) ->
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf5 = ?config(cc5,Config),
+ undefined = ?config(cc6,Config),
+ ok.
+
+conf6_tc1(Config) when is_list(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf5 = ?config(cc5,Config),
+ conf6 = ?config(cc6,Config),
+ ok.
+conf6_tc2(Config) when is_list(Config) ->
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf5 = ?config(cc5,Config),
+ conf6 = ?config(cc6,Config),
+ ok.
+
diff --git a/lib/test_server/test/test_server_conf02_SUITE.erl b/lib/test_server/test/test_server_conf02_SUITE.erl
new file mode 100644
index 0000000000..deba4660c6
--- /dev/null
+++ b/lib/test_server/test/test_server_conf02_SUITE.erl
@@ -0,0 +1,294 @@
+%%
+%% %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%
+%%
+
+%%%------------------------------------------------------------------
+%%% Test Server self test.
+%%%------------------------------------------------------------------
+-module(test_server_conf02_SUITE).
+-include_lib("test_server/include/test_server.hrl").
+
+-compile(export_all).
+
+all(doc) -> ["Test simple conf case structure, with and without nested cases"];
+all(suite) ->
+ [
+ {conf, conf1_init, [conf1_tc1, conf1_tc2], conf1_end},
+
+ {conf, [], conf2_init, [conf2_tc1, conf2_tc2], conf2_end},
+
+ {conf, conf3_init, [conf3_tc1,
+
+ {conf, [], conf4_init, [conf4_tc1, conf4_tc2], conf4_end},
+
+ conf3_tc2], conf3_end},
+
+ conf5
+ ].
+
+
+%%---------- conf cases ----------
+
+init_per_suite(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ [{suite,init}|Config].
+end_per_suite(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ ok.
+
+init_per_testcase(TC=conf1_tc1, Config) ->
+ init = ?config(suite,Config),
+ [{tc11,TC}|Config];
+init_per_testcase(TC=conf1_tc2, Config) ->
+ [{tc12,TC}|Config];
+init_per_testcase(TC=conf2_tc1, Config) ->
+ [{tc21,TC}|Config];
+init_per_testcase(TC=conf2_tc2, Config) ->
+ [{tc22,TC}|Config];
+init_per_testcase(TC=conf3_tc1, Config) ->
+ [{tc31,TC}|Config];
+init_per_testcase(TC=conf3_tc2, Config) ->
+ [{tc32,TC}|Config];
+init_per_testcase(TC=conf4_tc1, Config) ->
+ [{tc41,TC}|Config];
+init_per_testcase(TC=conf4_tc2, Config) ->
+ [{tc42,TC}|Config];
+init_per_testcase(TC=conf5_tc1, Config) ->
+ [{tc51,TC}|Config];
+init_per_testcase(TC=conf5_tc2, Config) ->
+ [{tc52,TC}|Config];
+init_per_testcase(TC=conf6_tc1, Config) ->
+ [{tc61,TC}|Config];
+init_per_testcase(TC=conf6_tc2, Config) ->
+ init = ?config(suite,Config),
+ [{tc62,TC}|Config].
+
+end_per_testcase(TC=conf1_tc1, Config) ->
+ init = ?config(suite,Config),
+ TC = ?config(tc11,Config),
+ ok;
+end_per_testcase(TC=conf1_tc2, Config) ->
+ TC = ?config(tc12,Config),
+ ok;
+end_per_testcase(TC=conf2_tc1, Config) ->
+ TC = ?config(tc21,Config),
+ ok;
+end_per_testcase(TC=conf2_tc2, Config) ->
+ TC = ?config(tc22,Config),
+ ok;
+end_per_testcase(TC=conf3_tc1, Config) ->
+ TC = ?config(tc31,Config),
+ ok;
+end_per_testcase(TC=conf3_tc2, Config) ->
+ TC = ?config(tc32,Config),
+ ok;
+end_per_testcase(TC=conf4_tc1, Config) ->
+ TC = ?config(tc41,Config),
+ ok;
+end_per_testcase(TC=conf4_tc2, Config) ->
+ TC = ?config(tc42,Config),
+ ok;
+end_per_testcase(TC=conf5_tc1, Config) ->
+ TC = ?config(tc51,Config),
+ ok;
+end_per_testcase(TC=conf5_tc2, Config) ->
+ TC = ?config(tc52,Config),
+ ok;
+end_per_testcase(TC=conf6_tc1, Config) ->
+ TC = ?config(tc61,Config),
+ ok;
+end_per_testcase(TC=conf6_tc2, Config) ->
+ init = ?config(suite,Config),
+ TC = ?config(tc62,Config),
+ ok.
+
+conf1_init(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ [{cc1,conf1}|Config].
+conf1_end(_Config) ->
+ ok.
+
+conf2_init(Config) when is_list(Config) ->
+ [{cc2,conf2}|Config].
+conf2_end(_Config) ->
+ ok.
+
+conf3_init(Config) when is_list(Config) ->
+ [{cc3,conf3}|Config].
+conf3_end(_Config) ->
+ ok.
+
+conf4_init(Config) when is_list(Config) ->
+ [{cc4,conf4}|Config].
+conf4_end(_Config) ->
+ ok.
+
+conf5_init(Config) when is_list(Config) ->
+ [{cc5,conf5}|Config].
+conf5_end(_Config) ->
+ ok.
+
+conf6_init(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ [{cc6,conf6}|Config].
+conf6_end(_Config) ->
+ ok.
+
+conf5(suite) -> % test specification
+ [{conf, conf5_init, [conf5_tc1,
+
+ {conf, [], conf6_init, [conf6_tc1, conf6_tc2], conf6_end},
+
+ conf5_tc2], conf5_end}].
+
+%%---------- test cases ----------
+
+conf1_tc1(Config) when is_list(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ conf1 = ?config(cc1,Config),
+ conf1_tc1 = ?config(tc11,Config),
+ ok.
+conf1_tc2(Config) when is_list(Config) ->
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ conf1 = ?config(cc1,Config),
+ conf1_tc2 = ?config(tc12,Config),
+ ok.
+
+conf2_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(cc1,Config),
+ undefined = ?config(tc11,Config),
+ conf2 = ?config(cc2,Config),
+ conf2_tc1 = ?config(tc21,Config),
+ ok.
+conf2_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ conf2 = ?config(cc2,Config),
+ undefined = ?config(tc21,Config),
+ conf2_tc2 = ?config(tc22,Config),
+ ok.
+
+conf3_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(tc22,Config),
+ conf3 = ?config(cc3,Config),
+ conf3_tc1 = ?config(tc31,Config),
+ ok.
+conf3_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ conf3 = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ undefined = ?config(tc31,Config),
+ undefined = ?config(tc41,Config),
+ conf3_tc2 = ?config(tc32,Config),
+ ok.
+
+conf4_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ conf3 = ?config(cc3,Config),
+ conf4 = ?config(cc4,Config),
+ undefined = ?config(tc32,Config),
+ conf4_tc1 = ?config(tc41,Config),
+ ok.
+conf4_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf3 = ?config(cc3,Config),
+ conf4 = ?config(cc4,Config),
+ undefined = ?config(tc41,Config),
+ conf4_tc2 = ?config(tc42,Config),
+ ok.
+
+conf5_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf5 = ?config(cc5,Config),
+ undefined = ?config(tc42,Config),
+ conf5_tc1 = ?config(tc51,Config),
+ ok.
+conf5_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf5 = ?config(cc5,Config),
+ undefined = ?config(cc6,Config),
+ undefined = ?config(tc51,Config),
+ undefined = ?config(tc62,Config),
+ conf5_tc2 = ?config(tc52,Config),
+ ok.
+
+conf6_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf5 = ?config(cc5,Config),
+ conf6 = ?config(cc6,Config),
+ undefined = ?config(tc52,Config),
+ conf6_tc1 = ?config(tc61,Config),
+ ok.
+conf6_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf5 = ?config(cc5,Config),
+ conf6 = ?config(cc6,Config),
+ undefined = ?config(tc61,Config),
+ conf6_tc2 = ?config(tc62,Config),
+ ok.
diff --git a/lib/test_server/test/test_server_line_SUITE.erl b/lib/test_server/test/test_server_line_SUITE.erl
new file mode 100644
index 0000000000..02897f164f
--- /dev/null
+++ b/lib/test_server/test/test_server_line_SUITE.erl
@@ -0,0 +1,122 @@
+%%
+%% %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%
+%%
+
+%%%------------------------------------------------------------------
+%%% Test Server self test.
+%%%------------------------------------------------------------------
+-module(test_server_line_SUITE).
+-include_lib("test_server/include/test_server.hrl").
+
+-export([all/1]).
+-export([init_per_testcase/2, fin_per_testcase/2]).
+-export([parse_transform/1, lines/1]).
+
+all(doc) -> ["Test of parse transform for collection line numbers"];
+all(suite) -> [parse_transform,lines].
+
+
+init_per_testcase(_Case, Config) ->
+ ?line test_server_line:clear(),
+ Dog = ?t:timetrap(?t:minutes(2)),
+ [{watchdog, Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ ?line test_server_line:clear(),
+ Dog=?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+parse_transform(suite) -> [];
+parse_transform(doc) -> [];
+parse_transform(Config) when is_list(Config) ->
+ ?line DataDir = ?config(data_dir,Config),
+ code:add_pathz(DataDir),
+
+ ?line ok = parse_transform_test:excluded(),
+ ?line [] = test_server_line:get_lines(),
+
+ ?line test_server_line:clear(),
+ ?line ok = parse_transform_test:func(),
+
+ ?line [{parse_transform_test,func4,58},
+ {parse_transform_test,func,49},
+ {parse_transform_test,func3,56},
+ {parse_transform_test,func,39},
+ {parse_transform_test,func2,54},
+ {parse_transform_test,func,36},
+ {parse_transform_test,func1,52},
+ {parse_transform_test,func,35}] = test_server_line:get_lines(),
+
+ code:del_path(DataDir),
+ ok.
+
+lines(suite) -> [];
+lines(doc) -> ["Test parse transform for collection line numbers"];
+lines(Config) when is_list(Config) ->
+ ?line L0 = [{mod,func,1},{mod,func,2},{mod,func,3},
+ {m,f,4},{m,f,5},{m,f,6},
+ {mo,fu,7},{mo,fu,8},{mo,fu,9}],
+ ?line LL = string:copies(L0, 1000),
+ ?line T1 = erlang:now(),
+ ?line lists:foreach(fun ({M,F,L}) ->
+ test_server_line:'$test_server_line'(M, F, L)
+ end, LL),
+ ?line T2 = erlang:now(),
+ ?line Long = test_server_line:get_lines(),
+ ?line test_server_line:clear(),
+
+ ?line T3 = erlang:now(),
+ ?line lists:foreach(fun ({M,F,L}) ->
+ test_server_line:'$test_server_lineQ'(M, F, L)
+ end, LL),
+ ?line T4 = erlang:now(),
+ ?line LongQ = test_server_line:get_lines(),
+
+ ?line io:format("'$test_server_line': ~f~n'$test_server_lineQ': ~f~n",
+ [timer:now_diff(T2, T1)/1000, timer:now_diff(T4, T3)/1000]),
+ ?line io:format("'$test_server_line' result long:~p~n", [Long]),
+ ?line io:format("'$test_server_lineQ' result long:~p~n", [LongQ]),
+
+ if Long =:= LongQ ->
+ ?line ok;
+ true ->
+ ?line ?t:fail("The two methods did not produce same result for"
+ " long lists of lines")
+ end,
+
+ ?line test_server_line:clear(),
+ ?line lists:foreach(fun ({M,F,L}) ->
+ test_server_line:'$test_server_line'(M, F, L)
+ end, L0),
+ ?line Short = test_server_line:get_lines(),
+ ?line test_server_line:clear(),
+ ?line lists:foreach(fun ({M,F,L}) ->
+ test_server_line:'$test_server_lineQ'(M, F, L)
+ end, L0),
+ ?line ShortQ = test_server_line:get_lines(),
+
+ ?line io:format("'$test_server_line' result short:~p~n", [Short]),
+ ?line io:format("'$test_server_lineQ' result short:~p~n", [ShortQ]),
+
+ if Short =:= ShortQ ->
+ ?line ok;
+ true ->
+ ?line ?t:fail("The two methods did not produce same result for"
+ " shot lists of lines\n")
+ end.
diff --git a/lib/test_server/test/test_server_line_SUITE_data/Makefile.src b/lib/test_server/test/test_server_line_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..a077648934
--- /dev/null
+++ b/lib/test_server/test/test_server_line_SUITE_data/Makefile.src
@@ -0,0 +1,6 @@
+EFLAGS=+debug_info -pa ../../test_server -I../../test_server
+
+all: parse_transform_test.@EMULATOR@
+
+parse_transform_test.@EMULATOR@: parse_transform_test.erl
+ erlc $(EFLAGS) parse_transform_test.erl
diff --git a/lib/test_server/test/test_server_line_SUITE_data/parse_transform_test.erl b/lib/test_server/test/test_server_line_SUITE_data/parse_transform_test.erl
new file mode 100644
index 0000000000..c3ee1b68cd
--- /dev/null
+++ b/lib/test_server/test/test_server_line_SUITE_data/parse_transform_test.erl
@@ -0,0 +1,59 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2009. 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(parse_transform_test).
+
+-include("test_server_line.hrl").
+-no_lines([{excluded,0}]).
+
+-export([excluded/0, func/0]).
+
+
+excluded() ->
+ line1,
+ line2,
+ ok.
+
+
+func() ->
+ hello,
+ func1(),
+ case func2() of
+ ok ->
+ helloagain,
+ case func3() of
+ ok ->
+ ok;
+ error ->
+ error
+ end;
+ error ->
+ error
+ end,
+ excluded(),
+ func4().
+
+func1() ->
+ ok.
+func2() ->
+ ok.
+func3() ->
+ error.
+func4() ->
+ ok.
+
diff --git a/lib/test_server/test/test_server_parallel01_SUITE.erl b/lib/test_server/test/test_server_parallel01_SUITE.erl
new file mode 100644
index 0000000000..0e7f329f89
--- /dev/null
+++ b/lib/test_server/test/test_server_parallel01_SUITE.erl
@@ -0,0 +1,518 @@
+%%
+%% %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%
+%%
+
+%%%------------------------------------------------------------------
+%%% Test Server self test.
+%%%------------------------------------------------------------------
+-module(test_server_parallel01_SUITE).
+-include_lib("test_server/include/test_server.hrl").
+
+-compile(export_all).
+
+%% -------------------------------------------------------------------
+%% Notes on parallel execution of test cases
+%% -------------------------------------------------------------------
+%%
+%% A group nested under a parallel group will start executing in
+%% parallel with previous (parallel) test cases (no matter what
+%% properties the nested group has). Test cases are however never
+%% executed in parallel with the start or end conf case of the same
+%% group! Because of this, the test_server_ctrl loop waits at
+%% the end conf of a group for all parallel cases to finish
+%% before the end conf case actually executes. This has the effect
+%% that it's only after a nested group has finished that any
+%% remaining parallel cases in the previous group get spawned (*).
+%% Example (all parallel cases):
+%%
+%% group1_init |---->
+%% group1_case1 | --------->
+%% group1_case2 | --------------------------------->
+%% group2_init | ---->
+%% group2_case1 | ------>
+%% group2_case2 | ---------->
+%% group2_end | --->
+%% group1_case3 (*)| ---->
+%% group1_case4 (*)| -->
+%% group1_end | --->
+%%
+
+all(doc) -> ["Test simple conf case structure, with and without nested cases"];
+all(suite) ->
+ [
+ {conf, [parallel], conf1_init, [conf1_tc1, conf1_tc2], conf1_end},
+
+ {conf, [parallel], conf2_init, [conf2_tc1, conf2_tc2], conf2_end},
+
+ {conf, [parallel], conf3_init, [conf3_tc1, conf3_tc1,
+
+ {conf, [],
+ conf4_init, [conf4_tc1, conf4_tc2], conf4_end},
+
+ conf3_tc2], conf3_end},
+
+ conf5,
+
+ {conf, [parallel], conf7_init, [conf7_tc1, conf7_tc1,
+
+ {conf, [parallel],
+ conf8_init, [conf8_tc1, conf8_tc2], conf8_end},
+
+ conf7_tc2], conf7_end}
+
+ ].
+
+
+%%---------- conf cases ----------
+
+init_per_suite(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ [{suite,init}|Config].
+end_per_suite(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ ok.
+
+init_per_testcase(TC=conf1_tc1, Config) ->
+ init = ?config(suite,Config),
+ [{tc11,TC}|Config];
+init_per_testcase(TC=conf1_tc2, Config) ->
+ [{tc12,TC}|Config];
+init_per_testcase(TC=conf2_tc1, Config) ->
+ [{tc21,TC}|Config];
+init_per_testcase(TC=conf2_tc2, Config) ->
+ [{tc22,TC}|Config];
+init_per_testcase(TC=conf3_tc1, Config) ->
+ [{tc31,TC}|Config];
+init_per_testcase(TC=conf3_tc2, Config) ->
+ [{tc32,TC}|Config];
+init_per_testcase(TC=conf4_tc1, Config) ->
+ [{tc41,TC}|Config];
+init_per_testcase(TC=conf4_tc2, Config) ->
+ [{tc42,TC}|Config];
+init_per_testcase(TC=conf5_tc1, Config) ->
+ [{tc51,TC}|Config];
+init_per_testcase(TC=conf5_tc2, Config) ->
+ [{tc52,TC}|Config];
+init_per_testcase(TC=conf6_tc1, Config) ->
+ [{tc61,TC}|Config];
+init_per_testcase(TC=conf6_tc2, Config) ->
+ init = ?config(suite,Config),
+ [{tc62,TC}|Config];
+init_per_testcase(TC=conf7_tc1, Config) ->
+ [{tc71,TC}|Config];
+init_per_testcase(TC=conf7_tc2, Config) ->
+ [{tc72,TC}|Config];
+init_per_testcase(TC=conf8_tc1, Config) ->
+ [{tc81,TC}|Config];
+init_per_testcase(TC=conf8_tc2, Config) ->
+ init = ?config(suite,Config),
+ [{tc82,TC}|Config].
+
+end_per_testcase(TC=conf1_tc1, Config) ->
+ init = ?config(suite,Config),
+ TC = ?config(tc11,Config),
+ ok;
+end_per_testcase(TC=conf1_tc2, Config) ->
+ TC = ?config(tc12,Config),
+ ok;
+end_per_testcase(TC=conf2_tc1, Config) ->
+ TC = ?config(tc21,Config),
+ ok;
+end_per_testcase(TC=conf2_tc2, Config) ->
+ TC = ?config(tc22,Config),
+ ok;
+end_per_testcase(TC=conf3_tc1, Config) ->
+ TC = ?config(tc31,Config),
+ ok;
+end_per_testcase(TC=conf3_tc2, Config) ->
+ TC = ?config(tc32,Config),
+ ok;
+end_per_testcase(TC=conf4_tc1, Config) ->
+ TC = ?config(tc41,Config),
+ ok;
+end_per_testcase(TC=conf4_tc2, Config) ->
+ TC = ?config(tc42,Config),
+ ok;
+end_per_testcase(TC=conf5_tc1, Config) ->
+ TC = ?config(tc51,Config),
+ ok;
+end_per_testcase(TC=conf5_tc2, Config) ->
+ TC = ?config(tc52,Config),
+ ok;
+end_per_testcase(TC=conf6_tc1, Config) ->
+ TC = ?config(tc61,Config),
+ ok;
+end_per_testcase(TC=conf6_tc2, Config) ->
+ init = ?config(suite,Config),
+ TC = ?config(tc62,Config),
+ ok;
+end_per_testcase(TC=conf7_tc1, Config) ->
+ TC = ?config(tc71,Config),
+ ok;
+end_per_testcase(TC=conf7_tc2, Config) ->
+ TC = ?config(tc72,Config),
+ ok;
+end_per_testcase(TC=conf8_tc1, Config) ->
+ TC = ?config(tc81,Config),
+ ok;
+end_per_testcase(TC=conf8_tc2, Config) ->
+ init = ?config(suite,Config),
+ TC = ?config(tc82,Config),
+ ok.
+
+conf1_init(Config) when is_list(Config) ->
+ test_server:comment(io_lib:format("~p",[now()])),
+ [parallel] = ?config(tc_group_properties,Config),
+ init = ?config(suite,Config),
+ [{t0,now()},{cc1,conf1}|Config].
+conf1_end(Config) ->
+ %% check 2s & 3s < 4s
+ Ms = timer:now_diff(now(),?config(t0,Config)),
+ test_server:comment(io_lib:format("~p",[now()])),
+ if Ms > 3500000 -> exit({bad_parallel_exec,Ms});
+ Ms < 3000000 -> exit({bad_parallel_exec,Ms});
+ true -> ok
+ end.
+
+conf2_init(Config) when is_list(Config) ->
+ test_server:comment(io_lib:format("~p",[now()])),
+ [parallel] = ?config(tc_group_properties,Config),
+ [{t0,now()},{cc2,conf2}|Config].
+conf2_end(Config) ->
+ %% check 3s & 2s < 4s
+ Ms = timer:now_diff(now(),?config(t0,Config)),
+ test_server:comment(io_lib:format("~p",[now()])),
+ if Ms > 3500000 -> exit({bad_parallel_exec,Ms});
+ Ms < 3000000 -> exit({bad_parallel_exec,Ms});
+ true -> ok
+ end.
+
+conf3_init(Config) when is_list(Config) ->
+ test_server:comment(io_lib:format("~p",[now()])),
+ [parallel] = ?config(tc_group_properties,Config),
+ [{t0,now()},{cc3,conf3}|Config].
+conf3_end(Config) ->
+ %% check 6s & 6s & (2s & 3s) & 1s = ~6s
+ Ms = timer:now_diff(now(),?config(t0,Config)),
+ test_server:comment(io_lib:format("~p",[now()])),
+ if Ms > 6500000 -> exit({bad_parallel_exec,Ms});
+ Ms < 6000000 -> exit({bad_parallel_exec,Ms});
+ true -> ok
+ end.
+
+conf4_init(Config) when is_list(Config) ->
+ test_server:comment(io_lib:format("~p",[now()])),
+ [] = ?config(tc_group_properties,Config),
+ [{t0,now()},{cc4,conf4}|Config].
+conf4_end(Config) ->
+ %% check 2s & 3s >= 5s
+ Ms = timer:now_diff(now(),?config(t0,Config)),
+ test_server:comment(io_lib:format("~p",[now()])),
+ if Ms > 5500000 -> exit({bad_parallel_exec,Ms});
+ Ms < 5000000 -> exit({bad_parallel_exec,Ms});
+ true -> ok
+ end.
+
+conf5_init(Config) when is_list(Config) ->
+ test_server:comment(io_lib:format("~p",[now()])),
+ [] = ?config(tc_group_properties,Config),
+ [{t0,now()},{cc5,conf5}|Config].
+conf5_end(Config) ->
+ %% check 1s & 1s & (3s & 2s) & 1s = ~6s
+ Ms = timer:now_diff(now(),?config(t0,Config)),
+ test_server:comment(io_lib:format("~p",[now()])),
+ if Ms > 7000000 -> exit({bad_parallel_exec,Ms});
+ Ms < 6000000 -> exit({bad_parallel_exec,Ms});
+ true -> ok
+ end.
+
+conf6_init(Config) when is_list(Config) ->
+ test_server:comment(io_lib:format("~p",[now()])),
+ [parallel] = ?config(tc_group_properties,Config),
+ init = ?config(suite,Config),
+ [{t0,now()},{cc6,conf6}|Config].
+conf6_end(Config) ->
+ %% check 3s & 2s < 5s
+ Ms = timer:now_diff(now(),?config(t0,Config)),
+ test_server:comment(io_lib:format("~p",[now()])),
+ if Ms > 3500000 -> exit({bad_parallel_exec,Ms});
+ Ms < 3000000 -> exit({bad_parallel_exec,Ms});
+ true -> ok
+ end.
+
+conf5(suite) -> % test specification
+ [{conf, conf5_init, [conf5_tc1, conf5_tc1,
+
+ {conf, [parallel], conf6_init, [conf6_tc1, conf6_tc2], conf6_end},
+
+ conf5_tc2], conf5_end}].
+
+conf7_init(Config) when is_list(Config) ->
+ test_server:comment(io_lib:format("~p",[now()])),
+ [parallel] = ?config(tc_group_properties,Config),
+ [{t0,now()},{cc7,conf7}|Config].
+conf7_end(Config) ->
+ %% check 1s & 1s & (2s & 2s) & 1s = ~3s
+ Ms = timer:now_diff(now(),?config(t0,Config)),
+ test_server:comment(io_lib:format("~p",[now()])),
+ if Ms > 3500000 -> exit({bad_parallel_exec,Ms});
+ Ms < 3000000 -> exit({bad_parallel_exec,Ms});
+ true -> ok
+ end.
+
+conf8_init(Config) when is_list(Config) ->
+ test_server:comment(io_lib:format("~p",[now()])),
+ [parallel] = ?config(tc_group_properties,Config),
+ init = ?config(suite,Config),
+ [{t0,now()},{cc8,conf8}|Config].
+conf8_end(Config) ->
+ %% check 2s & 2s < 4s
+ Ms = timer:now_diff(now(),?config(t0,Config)),
+ test_server:comment(io_lib:format("~p",[now()])),
+ if Ms > 2500000 -> exit({bad_parallel_exec,Ms});
+ Ms < 2000000 -> exit({bad_parallel_exec,Ms});
+ true -> ok
+ end.
+
+
+%%---------- test cases ----------
+
+conf1_tc1(Config) when is_list(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ conf1 = ?config(cc1,Config),
+ conf1_tc1 = ?config(tc11,Config),
+ timer:sleep(2000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+conf1_tc2(Config) when is_list(Config) ->
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ conf1 = ?config(cc1,Config),
+ conf1_tc2 = ?config(tc12,Config),
+ timer:sleep(3000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+
+conf2_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(cc1,Config),
+ undefined = ?config(tc11,Config),
+ conf2 = ?config(cc2,Config),
+ conf2_tc1 = ?config(tc21,Config),
+ timer:sleep(3000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+conf2_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ conf2 = ?config(cc2,Config),
+ undefined = ?config(tc21,Config),
+ conf2_tc2 = ?config(tc22,Config),
+ timer:sleep(2000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+
+conf3_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(tc22,Config),
+ conf3 = ?config(cc3,Config),
+ conf3_tc1 = ?config(tc31,Config),
+ timer:sleep(6000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+conf3_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ conf3 = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ undefined = ?config(tc31,Config),
+ undefined = ?config(tc41,Config),
+ conf3_tc2 = ?config(tc32,Config),
+ timer:sleep(1000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+
+conf4_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ conf3 = ?config(cc3,Config),
+ conf4 = ?config(cc4,Config),
+ undefined = ?config(tc32,Config),
+ conf4_tc1 = ?config(tc41,Config),
+ timer:sleep(2000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+conf4_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf3 = ?config(cc3,Config),
+ conf4 = ?config(cc4,Config),
+ undefined = ?config(tc41,Config),
+ conf4_tc2 = ?config(tc42,Config),
+ timer:sleep(3000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+
+conf5_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf5 = ?config(cc5,Config),
+ undefined = ?config(tc42,Config),
+ conf5_tc1 = ?config(tc51,Config),
+ timer:sleep(1000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+conf5_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf5 = ?config(cc5,Config),
+ undefined = ?config(cc6,Config),
+ undefined = ?config(tc51,Config),
+ undefined = ?config(tc62,Config),
+ conf5_tc2 = ?config(tc52,Config),
+ timer:sleep(1000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+
+conf6_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf5 = ?config(cc5,Config),
+ conf6 = ?config(cc6,Config),
+ undefined = ?config(tc52,Config),
+ conf6_tc1 = ?config(tc61,Config),
+ timer:sleep(3000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+conf6_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf5 = ?config(cc5,Config),
+ conf6 = ?config(cc6,Config),
+ undefined = ?config(tc61,Config),
+ conf6_tc2 = ?config(tc62,Config),
+ timer:sleep(2000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+
+conf7_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ undefined = ?config(cc5,Config),
+ undefined = ?config(cc6,Config),
+ conf7 = ?config(cc7,Config),
+ undefined = ?config(tc62,Config),
+ conf7_tc1 = ?config(tc71,Config),
+ timer:sleep(1000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+conf7_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf7 = ?config(cc7,Config),
+ undefined = ?config(cc8,Config),
+ undefined = ?config(tc71,Config),
+ undefined = ?config(tc82,Config),
+ conf7_tc2 = ?config(tc72,Config),
+ timer:sleep(1000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+
+conf8_tc1(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ undefined = ?config(cc5,Config),
+ undefined = ?config(cc6,Config),
+ conf7 = ?config(cc7,Config),
+ conf8 = ?config(cc8,Config),
+ undefined = ?config(tc72,Config),
+ conf8_tc1 = ?config(tc81,Config),
+ timer:sleep(2000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
+conf8_tc2(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf7 = ?config(cc7,Config),
+ conf8 = ?config(cc8,Config),
+ undefined = ?config(tc81,Config),
+ conf8_tc2 = ?config(tc82,Config),
+ timer:sleep(2000),
+ test_server:comment(io_lib:format("~p",[now()])),
+ ok.
diff --git a/lib/test_server/test/test_server_shuffle01_SUITE.erl b/lib/test_server/test/test_server_shuffle01_SUITE.erl
new file mode 100644
index 0000000000..7ad269501d
--- /dev/null
+++ b/lib/test_server/test/test_server_shuffle01_SUITE.erl
@@ -0,0 +1,471 @@
+%%
+%% %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%
+%%
+
+%%%------------------------------------------------------------------
+%%% Test Server self test.
+%%%------------------------------------------------------------------
+-module(test_server_shuffle01_SUITE).
+-include_lib("test_server/include/test_server.hrl").
+
+-compile(export_all).
+
+all(doc) -> ["Test simple conf case structure, with and without nested cases"];
+all(suite) ->
+ [
+ {conf, [shuffle], conf1_init, [conf1_tc1, conf1_tc2, conf1_tc3], conf1_end},
+
+ {conf, [{shuffle,{1,2,3}}], conf2_init, [conf2_tc1, conf2_tc2, conf2_tc3], conf2_end},
+
+ {conf, [shuffle], conf3_init, [conf3_tc1, conf3_tc2, conf3_tc3,
+
+ {conf, [], conf4_init,
+ [conf4_tc1, conf4_tc2], conf4_end}],
+ conf3_end},
+
+ conf5,
+
+ {conf, [shuffle,{repeat,5},parallel], conf7_init, [conf7_tc1,
+
+ {conf, [{shuffle,{3,2,1}},{repeat,3}],
+ conf8_init, [conf8_tc1, conf8_tc2, conf8_tc3],
+ conf8_end},
+
+ conf7_tc2, conf7_tc3], conf7_end}
+
+ ].
+
+
+%%---------- conf cases ----------
+
+init_per_suite(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ [{suite,init}|Config].
+end_per_suite(Config) ->
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ ok.
+
+init_per_testcase(TC=conf1_tc1, Config) ->
+ init = ?config(suite,Config),
+ [{tc11,TC}|Config];
+init_per_testcase(TC=conf1_tc2, Config) ->
+ [{tc12,TC}|Config];
+init_per_testcase(TC=conf1_tc3, Config) ->
+ [{tc13,TC}|Config];
+init_per_testcase(TC=conf2_tc1, Config) ->
+ [{tc21,TC}|Config];
+init_per_testcase(TC=conf2_tc2, Config) ->
+ [{tc22,TC}|Config];
+init_per_testcase(TC=conf2_tc3, Config) ->
+ [{tc23,TC}|Config];
+init_per_testcase(TC=conf3_tc1, Config) ->
+ [{tc31,TC}|Config];
+init_per_testcase(TC=conf3_tc2, Config) ->
+ [{tc32,TC}|Config];
+init_per_testcase(TC=conf3_tc3, Config) ->
+ [{tc33,TC}|Config];
+init_per_testcase(TC=conf4_tc1, Config) ->
+ [{tc41,TC}|Config];
+init_per_testcase(TC=conf4_tc2, Config) ->
+ [{tc42,TC}|Config];
+init_per_testcase(TC=conf5_tc1, Config) ->
+ [{tc51,TC}|Config];
+init_per_testcase(TC=conf5_tc2, Config) ->
+ [{tc52,TC}|Config];
+init_per_testcase(TC=conf6_tc1, Config) ->
+ [{tc61,TC}|Config];
+init_per_testcase(TC=conf6_tc2, Config) ->
+ init = ?config(suite,Config),
+ [{tc62,TC}|Config];
+init_per_testcase(TC=conf6_tc3, Config) ->
+ [{tc63,TC}|Config];
+init_per_testcase(TC=conf7_tc1, Config) ->
+ [{tc71,TC}|Config];
+init_per_testcase(TC=conf7_tc2, Config) ->
+ [{tc72,TC}|Config];
+init_per_testcase(TC=conf7_tc3, Config) ->
+ [{tc73,TC}|Config];
+init_per_testcase(TC=conf8_tc1, Config) ->
+ [{tc81,TC}|Config];
+init_per_testcase(TC=conf8_tc2, Config) ->
+ init = ?config(suite,Config),
+ [{tc82,TC}|Config];
+init_per_testcase(TC=conf8_tc3, Config) ->
+ [{tc83,TC}|Config].
+
+end_per_testcase(TC=conf1_tc1, Config) ->
+ init = ?config(suite,Config),
+ TC = ?config(tc11,Config),
+ ok;
+end_per_testcase(TC=conf1_tc2, Config) ->
+ TC = ?config(tc12,Config),
+ ok;
+end_per_testcase(TC=conf1_tc3, Config) ->
+ TC = ?config(tc13,Config),
+ ok;
+end_per_testcase(TC=conf2_tc1, Config) ->
+ TC = ?config(tc21,Config),
+ ok;
+end_per_testcase(TC=conf2_tc2, Config) ->
+ TC = ?config(tc22,Config),
+ ok;
+end_per_testcase(TC=conf2_tc3, Config) ->
+ TC = ?config(tc23,Config),
+ ok;
+end_per_testcase(TC=conf3_tc1, Config) ->
+ TC = ?config(tc31,Config),
+ ok;
+end_per_testcase(TC=conf3_tc2, Config) ->
+ TC = ?config(tc32,Config),
+ ok;
+end_per_testcase(TC=conf3_tc3, Config) ->
+ TC = ?config(tc33,Config),
+ ok;
+end_per_testcase(TC=conf4_tc1, Config) ->
+ TC = ?config(tc41,Config),
+ ok;
+end_per_testcase(TC=conf4_tc2, Config) ->
+ TC = ?config(tc42,Config),
+ ok;
+end_per_testcase(TC=conf5_tc1, Config) ->
+ TC = ?config(tc51,Config),
+ ok;
+end_per_testcase(TC=conf5_tc2, Config) ->
+ TC = ?config(tc52,Config),
+ ok;
+end_per_testcase(TC=conf6_tc1, Config) ->
+ TC = ?config(tc61,Config),
+ ok;
+end_per_testcase(TC=conf6_tc2, Config) ->
+ init = ?config(suite,Config),
+ TC = ?config(tc62,Config),
+ ok;
+end_per_testcase(TC=conf6_tc3, Config) ->
+ TC = ?config(tc63,Config),
+ ok;
+end_per_testcase(TC=conf7_tc1, Config) ->
+ TC = ?config(tc71,Config),
+ ok;
+end_per_testcase(TC=conf7_tc2, Config) ->
+ TC = ?config(tc72,Config),
+ ok;
+end_per_testcase(TC=conf7_tc3, Config) ->
+ TC = ?config(tc73,Config),
+ ok;
+end_per_testcase(TC=conf8_tc1, Config) ->
+ TC = ?config(tc81,Config),
+ ok;
+end_per_testcase(TC=conf8_tc2, Config) ->
+ init = ?config(suite,Config),
+ TC = ?config(tc82,Config),
+ ok;
+end_per_testcase(TC=conf8_tc3, Config) ->
+ TC = ?config(tc83,Config),
+ ok.
+
+
+conf1_init(Config) when is_list(Config) ->
+ init = ?config(suite,Config),
+ [{shuffle,{_,_,_}}] = ?config(tc_group_properties,Config),
+ test_server:comment("Shuffle (random seed)"),
+ [{cc1,conf1}|Config].
+conf1_end(_Config) ->
+ ok.
+
+conf2_init(Config) when is_list(Config) ->
+ [{shuffle,{1,2,3}}] = ?config(tc_group_properties,Config),
+ test_server:comment("Shuffle (user seed)"),
+ [{cc2,conf2}|Config].
+conf2_end(_Config) ->
+ ok.
+
+conf3_init(Config) when is_list(Config) ->
+ [{shuffle,{_,_,_}}] = ?config(tc_group_properties,Config),
+ test_server:comment("Shuffle (random)"),
+ [{cc3,conf3}|Config].
+conf3_end(_Config) ->
+ ok.
+
+conf4_init(Config) when is_list(Config) ->
+ [] = ?config(tc_group_properties,Config),
+ test_server:comment("No shuffle"),
+ [{cc4,conf4}|Config].
+conf4_end(_Config) ->
+ ok.
+
+conf5_init(Config) when is_list(Config) ->
+ [] = ?config(tc_group_properties,Config),
+ test_server:comment("No shuffle"),
+ [{cc5,conf5}|Config].
+conf5_end(_Config) ->
+ ok.
+
+conf6_init(Config) when is_list(Config) ->
+ [{shuffle,{_,_,_}}] = ?config(tc_group_properties,Config),
+ test_server:comment("Shuffle (random)"),
+ init = ?config(suite,Config),
+ [{cc6,conf6}|Config].
+conf6_end(_Config) ->
+ ok.
+
+conf5(suite) -> % test specification
+ [{conf, conf5_init, [conf5_tc1,
+
+ {conf, [shuffle], conf6_init,
+ [conf6_tc1, conf6_tc2, conf6_tc3],
+ conf6_end},
+
+ conf5_tc2], conf5_end}].
+
+conf7_init(Config) when is_list(Config) ->
+ test_server:comment("Group 7, Shuffle (random seed)"),
+ case proplists:get_value(shuffle,?config(tc_group_properties,Config)) of
+ {_,_,_} -> ok
+ end,
+ [{cc7,conf7}|Config].
+conf7_end(_Config) ->
+ ok.
+
+conf8_init(Config) when is_list(Config) ->
+ test_server:comment("Group 8, Shuffle (user start seed)"),
+ case proplists:get_value(shuffle,?config(tc_group_properties,Config)) of
+ {_,_,_} -> ok
+ end,
+ init = ?config(suite,Config),
+ [{cc8,conf8}|Config].
+conf8_end(_Config) ->
+ ok.
+
+
+%%---------- test cases ----------
+
+conf1_tc1(Config) when is_list(Config) ->
+ test_server:comment("Case 1"),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ conf1 = ?config(cc1,Config),
+ conf1_tc1 = ?config(tc11,Config),
+ ok.
+conf1_tc2(Config) when is_list(Config) ->
+ test_server:comment("Case 2"),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ init = ?config(suite,Config),
+ conf1 = ?config(cc1,Config),
+ conf1_tc2 = ?config(tc12,Config),
+ ok.
+conf1_tc3(suite) -> [];
+conf1_tc3(_Config) ->
+ test_server:comment("Case 3"),
+ ok.
+
+conf2_tc1(Config) when is_list(Config) ->
+ test_server:comment("Case 1"),
+ init = ?config(suite,Config),
+ undefined = ?config(cc1,Config),
+ conf2 = ?config(cc2,Config),
+ conf2_tc1 = ?config(tc21,Config),
+ ok.
+conf2_tc2(Config) when is_list(Config) ->
+ test_server:comment("Case 2"),
+ init = ?config(suite,Config),
+ conf2 = ?config(cc2,Config),
+ conf2_tc2 = ?config(tc22,Config),
+ ok.
+conf2_tc3(suite) -> [];
+conf2_tc3(_Config) ->
+ test_server:comment("Case 3"),
+ ok.
+
+conf3_tc1(Config) when is_list(Config) ->
+ test_server:comment("Case 1"),
+ init = ?config(suite,Config),
+ undefined = ?config(cc2,Config),
+ conf3 = ?config(cc3,Config),
+ conf3_tc1 = ?config(tc31,Config),
+ ok.
+conf3_tc2(Config) when is_list(Config) ->
+ test_server:comment("Case 2"),
+ init = ?config(suite,Config),
+ conf3 = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf3_tc2 = ?config(tc32,Config),
+ ok.
+conf3_tc3(suite) -> [];
+conf3_tc3(_Config) ->
+ test_server:comment("Case 3"),
+ ok.
+
+conf4_tc1(Config) when is_list(Config) ->
+ test_server:comment("Case 1"),
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ conf3 = ?config(cc3,Config),
+ conf4 = ?config(cc4,Config),
+ conf4_tc1 = ?config(tc41,Config),
+ ok.
+conf4_tc2(Config) when is_list(Config) ->
+ test_server:comment("Case 2"),
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf3 = ?config(cc3,Config),
+ conf4 = ?config(cc4,Config),
+ conf4_tc2 = ?config(tc42,Config),
+ ok.
+
+conf5_tc1(Config) when is_list(Config) ->
+ test_server:comment("Case 1"),
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf5 = ?config(cc5,Config),
+ conf5_tc1 = ?config(tc51,Config),
+ ok.
+conf5_tc2(Config) when is_list(Config) ->
+ test_server:comment("Case 2"),
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf5 = ?config(cc5,Config),
+ undefined = ?config(cc6,Config),
+ conf5_tc2 = ?config(tc52,Config),
+ ok.
+
+conf6_tc1(Config) when is_list(Config) ->
+ test_server:comment("Case 1"),
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ conf5 = ?config(cc5,Config),
+ conf6 = ?config(cc6,Config),
+ conf6_tc1 = ?config(tc61,Config),
+ ok.
+conf6_tc2(Config) when is_list(Config) ->
+ test_server:comment("Case 2"),
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf5 = ?config(cc5,Config),
+ conf6 = ?config(cc6,Config),
+ conf6_tc2 = ?config(tc62,Config),
+ ok.
+conf6_tc3(suite) -> [];
+conf6_tc3(_Config) ->
+ test_server:comment("Case 3"),
+ ok.
+
+conf7_tc1(Config) when is_list(Config) ->
+ test_server:comment("Case 1"),
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ undefined = ?config(cc5,Config),
+ undefined = ?config(cc6,Config),
+ conf7 = ?config(cc7,Config),
+ conf7_tc1 = ?config(tc71,Config),
+ ok.
+conf7_tc2(Config) when is_list(Config) ->
+ test_server:comment("Case 2"),
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf7 = ?config(cc7,Config),
+ undefined = ?config(cc8,Config),
+ conf7_tc2 = ?config(tc72,Config),
+ ok.
+conf7_tc3(suite) -> [];
+conf7_tc3(_Config) ->
+ test_server:comment("Case 3"),
+ ok.
+
+conf8_tc1(Config) when is_list(Config) ->
+ test_server:comment("Case 1"),
+ init = ?config(suite,Config),
+ case ?config(data_dir,Config) of
+ undefined -> exit(no_data_dir);
+ _ -> ok
+ end,
+ undefined = ?config(cc1,Config),
+ undefined = ?config(cc2,Config),
+ undefined = ?config(cc3,Config),
+ undefined = ?config(cc4,Config),
+ undefined = ?config(cc5,Config),
+ undefined = ?config(cc6,Config),
+ conf7 = ?config(cc7,Config),
+ conf8 = ?config(cc8,Config),
+ conf8_tc1 = ?config(tc81,Config),
+ ok.
+conf8_tc2(Config) when is_list(Config) ->
+ test_server:comment("Case 2"),
+ init = ?config(suite,Config),
+ case ?config(priv_dir,Config) of
+ undefined -> exit(no_priv_dir);
+ _ -> ok
+ end,
+ conf7 = ?config(cc7,Config),
+ conf8 = ?config(cc8,Config),
+ conf8_tc2 = ?config(tc82,Config),
+ ok.
+conf8_tc3(suite) -> [];
+conf8_tc3(_Config) ->
+ test_server:comment("Case 3"),
+ ok.
diff --git a/lib/test_server/test/test_server_skip_SUITE.erl b/lib/test_server/test/test_server_skip_SUITE.erl
new file mode 100644
index 0000000000..4037e1cc0e
--- /dev/null
+++ b/lib/test_server/test/test_server_skip_SUITE.erl
@@ -0,0 +1,43 @@
+%%
+%% %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%
+%%
+-module(test_server_skip_SUITE).
+
+-export([all/1, init_per_suite/1, end_per_suite/1]).
+-export([dummy/1]).
+
+-include_lib("test_server/include/test_server.hrl").
+-include_lib("test_server/include/test_server_line.hrl").
+
+all(suite) ->
+ [dummy].
+
+init_per_suite(Config) when is_list(Config) ->
+ {skip,"Skipping init_per_suite - check that \'dummy\' and"
+ " \'end_per_suite\' are also skipped"}.
+
+dummy(suite) -> [];
+dummy(doc) -> ["This testcase should never be executed"];
+dummy(Config) when is_list(Config) ->
+ ?t:fail("This testcase should be executed since"
+ " init_per_suite/1 is skipped").
+
+end_per_suite(doc) -> ["This testcase should never be executed"];
+end_per_suite(Config) when is_list(Config) ->
+ ?t:fail("end_per_suite/1 should not be executed when"
+ " init_per_suite/1 is skipped").
diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk
index 8e02fde8bc..e3aac682ec 100644
--- a/lib/test_server/vsn.mk
+++ b/lib/test_server/vsn.mk
@@ -1,2 +1,2 @@
-TEST_SERVER_VSN = 3.3.5
+TEST_SERVER_VSN = 3.3.6