aboutsummaryrefslogtreecommitdiffstats
path: root/lib/common_test
diff options
context:
space:
mode:
authorPeter Andersson <[email protected]>2010-06-04 15:34:42 +0200
committerRaimo Niskanen <[email protected]>2010-06-09 16:19:23 +0200
commit34cf18550ff792ed9da884b00a49d6accd1bd5f5 (patch)
treed81105e39baec08bba74932fc4490ad7e825acb7 /lib/common_test
parenta3af252253c1fbc642cf6229ff1e23f095b75b59 (diff)
downloadotp-34cf18550ff792ed9da884b00a49d6accd1bd5f5.tar.gz
otp-34cf18550ff792ed9da884b00a49d6accd1bd5f5.tar.bz2
otp-34cf18550ff792ed9da884b00a49d6accd1bd5f5.zip
Add support for dynamic timetrap handling
Diffstat (limited to 'lib/common_test')
-rw-r--r--lib/common_test/src/ct.erl14
-rw-r--r--lib/common_test/src/ct_config.erl35
-rw-r--r--lib/common_test/src/ct_run.erl25
-rw-r--r--lib/common_test/test/Makefile17
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl146
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl135
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl138
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl8
-rw-r--r--lib/common_test/test/ct_test_support.erl8
-rw-r--r--lib/common_test/test/ct_userconfig_callback.erl32
11 files changed, 503 insertions, 59 deletions
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index 307d10428d..77bcf34981 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -65,7 +65,7 @@
pal/1, pal/2, pal/3,
fail/1, comment/1,
testcases/2, userdata/2, userdata/3,
- sleep/1]).
+ timetrap/1, sleep/1]).
%% New API for manipulating with config handlers
-export([add_config/2, remove_config/2]).
@@ -844,6 +844,18 @@ remove_config(Callback, Config) ->
ct_config:remove_config(Callback, Config).
%%%-----------------------------------------------------------------
+%%% @spec timetrap(Time) -> ok
+%%% Time = {hours,Hours} | {minutes,Mins} | {seconds,Secs} | Millisecs | infinity
+%%% Hours = integer()
+%%% Mins = integer()
+%%% Secs = integer()
+%%% Millisecs = integer() | float()
+%%%
+%%% @doc <p>Use this function to set a new timetrap for the running test case.</p>
+timetrap(Time) ->
+ test_server:timetrap(Time).
+
+%%%-----------------------------------------------------------------
%%% @spec sleep(Time) -> ok
%%% Time = {hours,Hours} | {minutes,Mins} | {seconds,Secs} | Millisecs | infinity
%%% Hours = integer()
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index a6ade3f66b..dc6fcc66e5 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -694,39 +694,48 @@ random_bytes_1(N, Acc) -> random_bytes_1(N-1, [random:uniform(255)|Acc]).
check_callback_load(Callback) ->
case code:is_loaded(Callback) of
{file, _Filename}->
- {ok, Callback};
+ check_exports(Callback);
false->
case code:load_file(Callback) of
{module, Callback}->
- {ok, Callback};
+ check_exports(Callback);
{error, Error}->
{error, Error}
end
end.
+check_exports(Callback) ->
+ Fs = Callback:module_info(exports),
+ case {lists:member({check_parameter,1},Fs),
+ lists:member({read_config,1},Fs)} of
+ {true, true} ->
+ {ok, Callback};
+ _ ->
+ {error, missing_callback_functions}
+ end.
+
check_config_files(Configs) ->
ConfigChecker = fun
({Callback, [F|_R]=Files}) ->
case check_callback_load(Callback) of
- {ok, Callback}->
- if
- is_integer(F) ->
+ {ok, Callback} ->
+ if is_integer(F) ->
Callback:check_parameter(Files);
- is_list(F) ->
+ is_list(F) ->
lists:map(fun(File) ->
- Callback:check_parameter(File)
- end,
- Files)
+ Callback:check_parameter(File)
+ end,
+ Files)
end;
- {error, _}->
- {error, {callback, Callback}}
+ {error, Why}->
+ {error, {callback, {Callback,Why}}}
end;
({Callback, []}) ->
case check_callback_load(Callback) of
{ok, Callback}->
Callback:check_parameter([]);
- {error, _}->
- {error, {callback, Callback}}
+ {error, Why}->
+ {error, {callback, {Callback,Why}}}
end
end,
lists:keysearch(error, 1, lists:flatten(lists:map(ConfigChecker, Configs))).
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index f993985f52..ab900734f2 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -152,10 +152,12 @@ script_start1(Parent, Args) ->
%% read general start flags
Vts = get_start_opt(vts, true, Args),
Shell = get_start_opt(shell, true, Args),
- Cover = get_start_opt(cover, fun(CoverFile) -> ?abs(CoverFile) end, Args),
+ Cover = get_start_opt(cover, fun([CoverFile]) -> ?abs(CoverFile) end, Args),
LogDir = get_start_opt(logdir, fun([LogD]) -> LogD end, Args),
- MultTT = get_start_opt(multiply_timetraps, fun(MT) -> MT end, 1, Args),
- ScaleTT = get_start_opt(scale_timetraps, fun(CT) -> CT end, false, Args),
+ MultTT = get_start_opt(multiply_timetraps,
+ fun([MT]) -> list_to_integer(MT) end, 1, Args),
+ ScaleTT = get_start_opt(scale_timetraps,
+ fun([CT]) -> list_to_atom(CT) end, false, Args),
EvHandlers = event_handler_args2opts(Args),
%% check flags and set corresponding application env variables
@@ -335,8 +337,8 @@ check_and_install_configfiles(Configs, LogDir, EvHandlers) ->
{error,{cant_read_config_file,File}};
{value,{error,{wrong_config,Message}}}->
{error,{wrong_config,Message}};
- {value,{error,{callback,File}}} ->
- {error,{cant_load_callback_module,File}}
+ {value,{error,{callback,Info}}} ->
+ {error,{cant_load_callback_module,Info}}
end.
script_start3(StartOpts, Args) ->
@@ -745,14 +747,23 @@ run_prepared(Run, Skip, Opts = #opts{logdir = LogDir,
end.
check_config_file(Callback, File)->
+ case code:is_loaded(Callback) of
+ false ->
+ case code:load_file(Callback) of
+ {module,_} -> ok;
+ {error,Why} -> exit({cant_load_callback_module,Why})
+ end;
+ _ ->
+ ok
+ end,
case Callback:check_parameter(File) of
{ok,{file,File}}->
?abs(File);
{ok,{config,_}}->
File;
- {nok,{wrong_config,Message}}->
+ {error,{wrong_config,Message}}->
exit({wrong_config,{Callback,Message}});
- {nok,{nofile,File}}->
+ {error,{nofile,File}}->
exit({no_such_file,?abs(File)})
end.
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index eca6817682..594993cfec 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -27,6 +27,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk
MODULES= \
ct_test_support \
ct_test_support_eh \
+ ct_userconfig_callback \
ct_smoke_test_SUITE \
ct_event_handler_SUITE \
ct_groups_test_1_SUITE \
@@ -63,17 +64,17 @@ EBIN = .
# Targets
# ----------------------------------------------------
-#.PHONY: make_emakefile
+.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)
+make_emakefile:
+ $(ERL_TOP)/make/make_emakefile $(ERL_COMPILE_FLAGS) -o$(EBIN) $(MODULES)\
+ > $(EMAKEFILE)
-tests debug opt:
+tests debug opt: make_emakefile
+ erl $(ERL_MAKE_FLAGS) -make
clean:
+ rm -f $(EMAKEFILE)
rm -f $(TARGET_FILES)
rm -f core
@@ -86,7 +87,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
-release_tests_spec:
+release_tests_spec: make_emakefile
$(INSTALL_DIR) $(RELSYSDIR)
$(INSTALL_DATA) $(ERL_FILES) $(COVERFILE) $(RELSYSDIR)
$(INSTALL_PROGRAM) common_test.spec $(RELSYSDIR)
diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl
index edf28e0bca..11482f1508 100644
--- a/lib/common_test/test/ct_error_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE.erl
@@ -64,7 +64,9 @@ all(suite) ->
cfg_error,
lib_error,
no_compile,
- timetrap
+ timetrap_end_conf,
+ timetrap_normal,
+ timetrap_extended
].
@@ -87,7 +89,7 @@ cfg_error(Config) when is_list(Config) ->
Join(DataDir, "cfg_error_8_SUITE"),
Join(DataDir, "cfg_error_9_SUITE")
],
- {Opts,ERPid} = setup({suite,Suites}, Config),
+ {Opts,ERPid} = setup([{suite,Suites}], Config),
ok = ct_test_support:run(Opts, Config),
Events = ct_test_support:get_events(ERPid, Config),
@@ -105,7 +107,7 @@ 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),
+ {Opts,ERPid} = setup([{suite,Suites}], Config),
ok = ct_test_support:run(Opts, Config),
Events = ct_test_support:get_events(ERPid, Config),
@@ -123,7 +125,7 @@ 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),
+ {Opts,ERPid} = setup([{suite,Suites}], Config),
ok = ct_test_support:run(Opts, Config),
Events = ct_test_support:get_events(ERPid, Config),
@@ -136,21 +138,62 @@ no_compile(Config) when is_list(Config) ->
%%%-----------------------------------------------------------------
%%%
-timetrap(Config) when is_list(Config) ->
+timetrap_end_conf(Config) when is_list(Config) ->
DataDir = ?config(data_dir, Config),
Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
Suites = [Join(DataDir, "timetrap_1_SUITE")],
- {Opts,ERPid} = setup({suite,Suites}, Config),
+ {Opts,ERPid} = setup([{suite,Suites}], Config),
ok = ct_test_support:run(Opts, Config),
Events = ct_test_support:get_events(ERPid, Config),
- ct_test_support:log_events(timetrap,
+ ct_test_support:log_events(timetrap_end_conf,
reformat(Events, ?eh),
?config(priv_dir, Config)),
- TestEvents = events_to_check(timetrap),
+ TestEvents = events_to_check(timetrap_end_conf),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
+%%%-----------------------------------------------------------------
+%%%
+timetrap_normal(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suite = Join(DataDir, "timetrap_2_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},
+ {userconfig,{ct_userconfig_callback,
+ "multiply 1 scale false"}}],
+ Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(timetrap_normal,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = events_to_check(timetrap_normal),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+%%%-----------------------------------------------------------------
+%%%
+timetrap_extended(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Join = fun(D, S) -> filename:join(D, "error/test/"++S) end,
+ Suite = Join(DataDir, "timetrap_2_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},
+ {multiply_timetraps,2},
+ {scale_timetraps,false},
+ {userconfig,{ct_userconfig_callback,
+ "multiply 2 scale false"}}],
+ Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(timetrap_extended,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config)),
+
+ TestEvents = events_to_check(timetrap_extended),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
@@ -160,7 +203,7 @@ 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 = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test],
ERPid = ct_test_support:start_event_receiver(Config),
{Opts,ERPid}.
@@ -584,18 +627,77 @@ test_events(lib_error) ->
test_events(no_compile) ->
[];
-test_events(timetrap) ->
+test_events(timetrap_end_conf) ->
[
- {?eh,start_logging,{'DEF','RUNDIR'}},
- {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{1,1,1}},
- {?eh,tc_start,{timetrap_1_SUITE,init_per_suite}},
- {?eh,tc_done,{timetrap_1_SUITE,init_per_suite,ok}},
- {?eh,tc_start,{timetrap_1_SUITE,tc1}},
- {?eh,tc_done,{timetrap_1_SUITE,tc1,{failed,{timetrap_timeout,1000}}}},
- {?eh,test_stats,{0,1,{0,0}}},
- {?eh,tc_start,{timetrap_1_SUITE,end_per_suite}},
- {?eh,tc_done,{timetrap_1_SUITE,end_per_suite,ok}},
- {?eh,test_done,{'DEF','STOP_TIME'}},
- {?eh,stop_logging,[]}
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,3}},
+ {?eh,tc_start,{timetrap_1_SUITE,init_per_suite}},
+ {?eh,tc_done,{timetrap_1_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_1_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_1_SUITE,tc1,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,{timetrap_1_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_1_SUITE,tc2,{failed,{testcase_aborted,testing_end_conf}}}},
+ {?eh,test_stats,{0,2,{0,0}}},
+ {?eh,tc_start,{timetrap_1_SUITE,tc3}},
+ {?eh,tc_done,
+ {timetrap_1_SUITE,tc3,{failed,{testcase_aborted,testing_end_conf}}}},
+ {?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_start,{timetrap_1_SUITE,end_per_suite}},
+ {?eh,tc_done,{timetrap_1_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(timetrap_normal) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,3}},
+ {?eh,tc_start,{timetrap_2_SUITE,init_per_suite}},
+ {?eh,tc_done,{timetrap_2_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_2_SUITE,tc0}},
+ {?eh,tc_done,
+ {timetrap_2_SUITE,tc0,{failed,{timetrap_timeout,3000}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,{timetrap_2_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_2_SUITE,tc1,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,2,{0,0}}},
+ {?eh,tc_start,{timetrap_2_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_2_SUITE,tc2,{failed,{timetrap_timeout,500}}}},
+ {?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_start,{timetrap_2_SUITE,end_per_suite}},
+ {?eh,tc_done,{timetrap_2_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+
+test_events(timetrap_extended) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,3}},
+ {?eh,tc_start,{timetrap_2_SUITE,init_per_suite}},
+ {?eh,tc_done,{timetrap_2_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{timetrap_2_SUITE,tc0}},
+ {?eh,tc_done,
+ {timetrap_2_SUITE,tc0,{failed,{timetrap_timeout,6000}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,{timetrap_2_SUITE,tc1}},
+ {?eh,tc_done,
+ {timetrap_2_SUITE,tc1,{failed,{timetrap_timeout,2000}}}},
+ {?eh,test_stats,{0,2,{0,0}}},
+ {?eh,tc_start,{timetrap_2_SUITE,tc2}},
+ {?eh,tc_done,
+ {timetrap_2_SUITE,tc2,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_start,{timetrap_2_SUITE,end_per_suite}},
+ {?eh,tc_done,{timetrap_2_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
].
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl
new file mode 100644
index 0000000000..2e6432d05d
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_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(timetrap_1_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(tc3, Config) ->
+ [{default_timeout,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(tc1, Config) ->
+ ct:pal("tc1: ~p", [Config]),
+ ok;
+
+end_per_testcase(tc2, Config) ->
+ ct:pal("tc2: ~p", [Config]),
+ ok;
+
+end_per_testcase(tc3, Config) ->
+ ct:pal("tc3: ~p", [Config]),
+ ct:sleep(10000),
+ 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,tc3].
+
+tc1(_) ->
+ ct:sleep(3000),
+ ok.
+
+tc2(_) ->
+ spawn(ct, abort_current_testcase, [testing_end_conf]),
+ timer:sleep(3000),
+ ok.
+
+tc3(_) ->
+ spawn(ct, abort_current_testcase, [testing_end_conf]),
+ timer:sleep(3000),
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl
new file mode 100644
index 0000000000..b785d330aa
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_2_SUITE.erl
@@ -0,0 +1,138 @@
+%%
+%% %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(timetrap_2_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,3}},
+ {require,multiply},
+ {require,scale}].
+
+%%--------------------------------------------------------------------
+%% 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) ->
+ ct:timetrap({seconds,1}),
+ Config;
+
+init_per_testcase(tc3, Config) ->
+ ct:timetrap({seconds,1}),
+ 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(_, Config) ->
+ ok.
+
+%%--------------------------------------------------------------------
+%% Function: groups() -> [Group]
+%% Group = {GroupName,Properties,GroupsAndTestCases}
+%% GroupName = atom()
+%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}]
+%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase]
+%% TestCase = atom()
+%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}}
+%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail |
+%% repeat_until_any_ok | repeat_until_any_fail
+%% N = integer() | forever
+%%--------------------------------------------------------------------
+groups() ->
+ [].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [tc0,tc1,tc2].
+
+tc0(_) ->
+ N = list_to_integer(ct:get_config(multiply)),
+ ct:comment(io_lib:format("TO after ~w sec", [3*N])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc1(_) ->
+ N =list_to_integer( ct:get_config(multiply)),
+ ct:comment(io_lib:format("TO after ~w sec", [1*N])),
+ ct:sleep({seconds,5}),
+ ok.
+
+tc2(_) ->
+ N = list_to_integer(ct:get_config(multiply)),
+ ct:comment(io_lib:format("TO after ~w sec", [0.5*N])),
+ ct:timetrap(500),
+ ct:sleep(2000),
+ 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
index 8b46a30cdc..eb85409073 100644
--- a/lib/common_test/test/ct_test_server_if_1_SUITE.erl
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE.erl
@@ -202,14 +202,14 @@ test_events(ts_if_1) ->
{?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,tc_done,{ts_if_1_SUITE,tc12,{failed,{testcase_aborted,'stopping 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}}}}}},
diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
index 8e90df21ce..47cea190dd 100644
--- a/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
+++ b/lib/common_test/test/ct_test_server_if_1_SUITE_data/test_server_if/test/ts_if_1_SUITE.erl
@@ -93,6 +93,10 @@ init_per_testcase(_TestCase, Config) ->
%%--------------------------------------------------------------------
end_per_testcase(tc2, Config) ->
timer:sleep(5000);
+end_per_testcase(tc12, Config) ->
+ ct:comment("end_per_testcase(tc12) called!"),
+ ct:pal("end_per_testcase(tc12) called!", []),
+ ok;
end_per_testcase(_TestCase, _Config) ->
ok.
@@ -180,9 +184,9 @@ gtc2(_) ->
exit(should_have_been_skipped).
tc12(_) ->
- F = fun() -> ct:abort_current_testcase({abort_current_testcase,tc12}) end,
+ F = fun() -> ct:abort_current_testcase('stopping tc12') end,
spawn(F),
- timer:sleep(500),
+ timer:sleep(1000),
exit(should_have_been_aborted).
tc13(_) ->
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index c7c7384847..9ce8529bdb 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -110,11 +110,11 @@ init_per_testcase(_TestCase, Config) ->
{_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
case lists:keysearch(master, 1, Config) of
false->
- test_server:format("See Common Test logs here:\n"
+ test_server:format("See Common Test logs here:\n\n"
"<a href=\"file://~s/all_runs.html\">~s/all_runs.html</a>",
[LogDir,LogDir]);
{value, _}->
- test_server:format("See CT Master Test logs here:\n"
+ test_server:format("See CT Master Test logs here:\n\n"
"<a href=\"file://~s/master_runs.html\">~s/master_runs.html</a>",
[LogDir,LogDir])
end,
@@ -183,14 +183,14 @@ run(Opts, Config) ->
CTNode = ?config(ct_node, Config),
Level = ?config(trace_level, Config),
%% use ct interface
- test_server:format(Level, "Calling ct:run_test(~p) on ~p~n",
+ test_server:format(Level, "[RUN #1] Calling ct:run_test(~p) on ~p~n",
[Opts, CTNode]),
Result1 = rpc:call(CTNode, ct, run_test, [Opts]),
%% use run_test interface (simulated)
test_server:format(Level, "Saving start opts on ~p: ~p~n", [CTNode,Opts]),
rpc:call(CTNode, application, set_env, [common_test, run_test_start_opts, Opts]),
- test_server:format(Level, "Calling ct_run:script_start() on ~p~n", [CTNode]),
+ test_server:format(Level, "[RUN #2] Calling ct_run:script_start() on ~p~n", [CTNode]),
Result2 = rpc:call(CTNode, ct_run, script_start, []),
case {Result1,Result2} of
{ok,ok} ->
diff --git a/lib/common_test/test/ct_userconfig_callback.erl b/lib/common_test/test/ct_userconfig_callback.erl
new file mode 100644
index 0000000000..ca51bf240b
--- /dev/null
+++ b/lib/common_test/test/ct_userconfig_callback.erl
@@ -0,0 +1,32 @@
+%%--------------------------------------------------------------------
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+-module(ct_userconfig_callback).
+
+-export([check_parameter/1, read_config/1]).
+
+read_config(Str) ->
+ KeyVals = string:tokens(Str, " "),
+ {ok,read_config1(KeyVals)}.
+
+read_config1([Key,Val | KeyVals]) ->
+ [{list_to_atom(Key),Val} | read_config1(KeyVals)];
+read_config1([]) ->
+ [].
+
+check_parameter(Str) ->
+ {ok,{config,Str}}.