aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Andersson <[email protected]>2010-06-07 17:28:01 +0200
committerRaimo Niskanen <[email protected]>2010-06-09 16:19:25 +0200
commit2dbeff631ce93744972cb04039d434aa172d28f4 (patch)
tree23b1ddfd4a41658cf3e9592f14b132111cfe8a47
parent4ed31623e145531a1aa84f6c1091481820f62099 (diff)
downloadotp-2dbeff631ce93744972cb04039d434aa172d28f4.tar.gz
otp-2dbeff631ce93744972cb04039d434aa172d28f4.tar.bz2
otp-2dbeff631ce93744972cb04039d434aa172d28f4.zip
Fix so that ct_run converts relative diretories in the code path to absolute
Directories added with run_test -pa or -pz in the pre erl_args part of the command line will be converted from relative to absolute, this to avoid confusion when Common Test switches working directory during the test run. Also fixed in this commit: Problem with timeouts during init_tc or end_tc (in the Test Server framework).
-rw-r--r--lib/common_test/src/ct_run.erl52
-rw-r--r--lib/common_test/test/Makefile14
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl35
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_12_SUITE.erl22
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_13_SUITE.erl47
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_14_SUITE.erl46
-rw-r--r--lib/test_server/src/test_server.erl136
-rw-r--r--lib/test_server/src/test_server_sup.erl1
8 files changed, 282 insertions, 71 deletions
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 2d79021ce4..9dc0bff26a 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -77,6 +77,12 @@ script_start() ->
Init = init:get_arguments(),
CtArgs = lists:takewhile(fun({ct_erl_args,_}) -> false;
(_) -> true end, Init),
+
+ %% convert relative dirs added with pa or pz (pre erl_args on
+ %% the run_test command line) to absolute so that app modules
+ %% can be found even after CT changes CWD to logdir
+ rel_to_abs(CtArgs),
+
Args =
case application:get_env(common_test, run_test_start_opts) of
{ok,EnvStartOpts} ->
@@ -1910,9 +1916,51 @@ event_handler_init_args2opts([EH, Arg]) ->
event_handler_init_args2opts([]) ->
[].
-%% this function translates ct:run_test/1 start options
+%% This function reads pa and pz arguments, converts dirs from relative
+%% to absolute, and re-inserts them in the code path. The order of the
+%% dirs in the code path remain the same. Note however that since this
+%% function is only used for arguments "pre run_test erl_args", the order
+%% relative dirs "post run_test erl_args" is not kept!
+rel_to_abs(CtArgs) ->
+ {PA,PZ} = get_pa_pz(CtArgs, [], []),
+ io:format(user, "~n", []),
+ [begin
+ code:del_path(filename:basename(D)),
+ Abs = filename:absname(D),
+ code:add_pathz(Abs),
+ if D /= Abs ->
+ io:format(user, "Converting ~p to ~p and re-inserting "
+ "with add_pathz/1~n",
+ [D, Abs]);
+ true ->
+ ok
+ end
+ end || D <- PZ],
+ [begin
+ code:del_path(filename:basename(D)),
+ Abs = filename:absname(D),
+ code:add_patha(Abs),
+ if D /= Abs ->
+ io:format(user, "Converting ~p to ~p and re-inserting "
+ "with add_patha/1~n",
+ [D, Abs]);
+ true ->ok
+ end
+ end || D <- PA],
+ io:format(user, "~n", []).
+
+get_pa_pz([{pa,Dirs} | Args], PA, PZ) ->
+ get_pa_pz(Args, PA ++ Dirs, PZ);
+get_pa_pz([{pz,Dirs} | Args], PA, PZ) ->
+ get_pa_pz(Args, PA, PZ ++ Dirs);
+get_pa_pz([_ | Args], PA, PZ) ->
+ get_pa_pz(Args, PA, PZ);
+get_pa_pz([], PA, PZ) ->
+ {PA,PZ}.
+
+%% This function translates ct:run_test/1 start options
%% to run_test start arguments (on the init arguments format) -
-%% this is useful mainly for testing the ct_run start functions
+%% this is useful mainly for testing the ct_run start functions.
opts2args(EnvStartOpts) ->
lists:flatmap(fun({config,CfgFiles}) ->
[{ct_config,[CfgFiles]}];
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index 2f1ff9a835..97ded5eb9a 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -65,18 +65,18 @@ EBIN = .
# Targets
# ----------------------------------------------------
-.PHONY: make_emakefile
+#.PHONY: make_emakefile
-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: make_emakefile
+tests debug opt:
erl $(ERL_MAKE_FLAGS) -make
clean:
- rm -f $(EMAKEFILE)
rm -f $(TARGET_FILES)
+# rm -f $(EMAKEFILE)
rm -f core
docs:
@@ -88,7 +88,7 @@ include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
-release_tests_spec: make_emakefile
+release_tests_spec:
$(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 7327fa5816..2fa031b884 100644
--- a/lib/common_test/test/ct_error_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE.erl
@@ -90,7 +90,9 @@ cfg_error(Config) when is_list(Config) ->
Join(DataDir, "cfg_error_9_SUITE"),
Join(DataDir, "cfg_error_10_SUITE"),
Join(DataDir, "cfg_error_11_SUITE"),
- Join(DataDir, "cfg_error_12_SUITE")
+ Join(DataDir, "cfg_error_12_SUITE"),
+ Join(DataDir, "cfg_error_13_SUITE"),
+ Join(DataDir, "cfg_error_14_SUITE")
],
{Opts,ERPid} = setup([{suite,Suites}], Config),
ok = ct_test_support:run(Opts, Config),
@@ -231,7 +233,7 @@ test_events(cfg_error) ->
[
{?eh,start_logging,{'DEF','RUNDIR'}},
{?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
- {?eh,start_info,{12,12,39}},
+ {?eh,start_info,{14,14,42}},
{?eh,tc_start,{cfg_error_1_SUITE,init_per_suite}},
{?eh,tc_done,
@@ -568,15 +570,34 @@ test_events(cfg_error) ->
{?eh,tc_done,{cfg_error_12_SUITE,tc1,{failed,{timetrap_timeout,500}}}},
{?eh,test_stats,{13,4,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc2}},
- {?eh,tc_done,{cfg_error_12_SUITE,tc2,
- {failed,
- {cfg_error_12_SUITE,end_per_testcase,
- {timetrap_timeout,500}}}}},
+ {?eh,tc_done,{cfg_error_12_SUITE,tc2,{failed,
+ {cfg_error_12_SUITE,end_per_testcase,
+ {timetrap_timeout,500}}}}},
{?eh,test_stats,{14,4,{1,19}}},
{?eh,tc_start,{cfg_error_12_SUITE,tc3}},
{?eh,tc_done,{cfg_error_12_SUITE,tc3,ok}},
{?eh,test_stats,{15,4,{1,19}}},
-
+ {?eh,tc_start,{cfg_error_12_SUITE,tc4}},
+ {?eh,tc_done,{cfg_error_12_SUITE,tc4,{failed,
+ {cfg_error_12_SUITE,end_per_testcase,
+ {timetrap_timeout,500}}}}},
+ {?eh,test_stats,{16,4,{1,19}}},
+ {?eh,tc_start,{cfg_error_13_SUITE,init_per_suite}},
+ {?eh,tc_done,{cfg_error_13_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{cfg_error_13_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_13_SUITE,tc1,ok}},
+ {?eh,test_stats,{17,4,{1,19}}},
+ {?eh,tc_start,{cfg_error_13_SUITE,end_per_suite}},
+ {?eh,tc_done,{cfg_error_13_SUITE,end_per_suite,ok}},
+ {?eh,tc_start,{cfg_error_14_SUITE,init_per_suite}},
+ {?eh,tc_done,{cfg_error_14_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{cfg_error_14_SUITE,tc1}},
+ {?eh,tc_done,{cfg_error_14_SUITE,tc1,ok}},
+ {?eh,test_stats,{18,4,{1,19}}},
+ {?eh,tc_start,{cfg_error_14_SUITE,end_per_suite}},
+ {?eh,tc_done,{cfg_error_14_SUITE,end_per_suite,
+ {comment,
+ "should succeed since ct_fw cancels timetrap in end_tc"}}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}
];
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_12_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_12_SUITE.erl
index 271eaa673e..75f00c1de3 100644
--- a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_12_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_12_SUITE.erl
@@ -22,14 +22,20 @@
-include_lib("common_test/include/ct.hrl").
+init_per_testcase(_, Config) ->
+ Config.
+
end_per_testcase(tc2, _Config) ->
timer:sleep(2000),
exit(this_should_not_be_printed);
+end_per_testcase(tc4, _Config) ->
+ timer:sleep(2000),
+ exit(this_should_not_be_printed);
end_per_testcase(_, _) ->
ok.
all() ->
- [tc1, tc2, tc3].
+ [tc1, tc2, tc3, tc4].
%%%-----------------------------------------------------------------
tc1() ->
@@ -66,3 +72,17 @@ tc3(_) ->
(_, Default) -> Default
end),
{comment,"should succeed since ct_fw cancels timetrap in end_tc"}.
+
+%%%-----------------------------------------------------------------
+tc4() ->
+ put('$test_server_framework_test',
+ fun(end_tc, _Default) ->
+ ct:pal("end_tc(~p): Night time...",[self()]),
+ timer:sleep(1000),
+ ct:pal("end_tc(~p): Day time!",[self()]);
+ (_, Default) -> Default
+ end),
+ [{timetrap,500}].
+
+tc4(_) ->
+ ok.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_13_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_13_SUITE.erl
new file mode 100644
index 0000000000..d1c18d0bb0
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_13_SUITE.erl
@@ -0,0 +1,47 @@
+%%
+%% %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_13_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+init_per_suite() ->
+ put('$test_server_framework_test',
+ fun(end_tc, _Default) ->
+ ct:pal("end_tc(~p): Night time...",[self()]),
+ timer:sleep(1000),
+ ct:pal("end_tc(~p): Day time!",[self()]);
+ (_, Default) -> Default
+ end),
+ [{timetrap,500}].
+
+init_per_suite(Config) ->
+ ct:comment("should succeed since ct_fw cancels timetrap in end_tc"),
+ Config.
+
+end_per_suite(_) ->
+ ok.
+
+all() ->
+ [tc1].
+
+%%%-----------------------------------------------------------------
+tc1(_) ->
+ dummy.
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_14_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_14_SUITE.erl
new file mode 100644
index 0000000000..367f5f06d6
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/cfg_error_14_SUITE.erl
@@ -0,0 +1,46 @@
+%%
+%% %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_14_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite() ->
+ put('$test_server_framework_test',
+ fun(end_tc, _Default) ->
+ ct:pal("end_tc(~p): Night time...",[self()]),
+ timer:sleep(1000),
+ ct:pal("end_tc(~p): Day time!",[self()]);
+ (_, Default) -> Default
+ end),
+ [{timetrap,500}].
+
+end_per_suite(_Config) ->
+ {comment,"should succeed since ct_fw cancels timetrap in end_tc"}.
+
+all() ->
+ [tc1].
+
+%%%-----------------------------------------------------------------
+tc1(_) ->
+ dummy.
diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl
index 940935edf5..acc9dbaab8 100644
--- a/lib/test_server/src/test_server.erl
+++ b/lib/test_server/src/test_server.erl
@@ -737,64 +737,91 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) ->
case Reason of
{timetrap_timeout,TVal,Loc} ->
%% convert Loc to form that can be formatted
- Loc1 = mod_loc(Loc),
- {Mod,Func} = get_mf(Loc1),
- %% call end_per_testcase on a separate process, only so that the
- %% user has a chance to clean up after init_per_testcase, even
- %% after a timetrap timeout
- NewCurrConf =
- case CurrConf of
- {{Mod,Func},Conf} ->
- EndConfPid =
- call_end_conf(Mod,Func,Pid,
- {timetrap_timeout,TVal},
- Loc1,[{tc_status,
- {failed,
- timetrap_timeout}}|Conf],
- TVal),
- {EndConfPid,{Mod,Func},Conf};
- _ ->
- %% The framework functions mustn't execute on this
- %% group leader process or io will cause deadlock,
- %% so we spawn a dedicated process for the operation
- %% and let the group leader go back to handle io.
- spawn_fw_call(Mod,Func,Pid,{timetrap_timeout,TVal},
- Loc1,self(),Comment),
- undefined
- end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
- Comment,NewCurrConf);
+ case mod_loc(Loc) of
+ {FwMod,FwFunc,framework} ->
+ %% timout during framework call
+ spawn_fw_call(FwMod,FwFunc,Pid,
+ {framework_error,{timetrap,TVal}},
+ unknown,self(),Comment),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
+ Comment,undefined);
+ Loc1 ->
+ {Mod,Func} = get_mf(Loc1),
+ %% call end_per_testcase on a separate process,
+ %% only so that the user has a chance to clean up
+ %% after init_per_testcase, even after a timetrap timeout
+ NewCurrConf =
+ case CurrConf of
+ {{Mod,Func},Conf} ->
+ EndConfPid =
+ call_end_conf(Mod,Func,Pid,
+ {timetrap_timeout,TVal},
+ Loc1,[{tc_status,
+ {failed,
+ timetrap_timeout}}|Conf],
+ TVal),
+ {EndConfPid,{Mod,Func},Conf};
+ _ ->
+ %% The framework functions mustn't execute on this
+ %% group leader process or io will cause deadlock,
+ %% so we spawn a dedicated process for the operation
+ %% and let the group leader go back to handle io.
+ spawn_fw_call(Mod,Func,Pid,{timetrap_timeout,TVal},
+ Loc1,self(),Comment),
+ undefined
+ end,
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
+ Comment,NewCurrConf)
+ end;
{timetrap_timeout,TVal,Loc,InitOrEnd} ->
- Loc1 = mod_loc(Loc),
- {Mod,_Func} = get_mf(Loc1),
- spawn_fw_call(Mod,InitOrEnd,Pid,{timetrap_timeout,TVal},
- Loc1,self(),Comment),
+ case mod_loc(Loc) of
+ {FwMod,FwFunc,framework} ->
+ %% timout during framework call
+ spawn_fw_call(FwMod,FwFunc,Pid,
+ {framework_error,{timetrap,TVal}},
+ unknown,self(),Comment);
+ Loc1 ->
+ {Mod,_Func} = get_mf(Loc1),
+ spawn_fw_call(Mod,InitOrEnd,Pid,{timetrap_timeout,TVal},
+ Loc1,self(),Comment)
+ end,
run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf);
{testcase_aborted,AbortReason,AbortLoc} ->
- Loc1 = mod_loc(AbortLoc),
- {Mod,Func} = get_mf(Loc1),
- %% call end_per_testcase on a separate process, only so that the
- %% user has a chance to clean up after init_per_testcase, even
- %% after abortion
ErrorMsg = {testcase_aborted,AbortReason},
- NewCurrConf =
- case CurrConf of
- {{Mod,Func},Conf} ->
- TVal = case lists:keysearch(default_timeout,1,Conf) of
- {value,{default_timeout,Tmo}} -> Tmo;
- _ -> ?DEFAULT_TIMETRAP_SECS*1000
- end,
- EndConfPid =
- call_end_conf(Mod,Func,Pid,ErrorMsg,
- Loc1,[{tc_status,{failed,ErrorMsg}}|Conf],
- TVal),
- {EndConfPid,{Mod,Func},Conf};
- _ ->
- spawn_fw_call(Mod,Func,Pid,ErrorMsg,
- Loc1,self(),Comment),
- undefined
- end,
- run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,NewCurrConf);
+ case mod_loc(AbortLoc) of
+ {FwMod,FwFunc,framework} ->
+ %% abort during framework call
+ spawn_fw_call(FwMod,FwFunc,Pid,
+ {framework_error,ErrorMsg},
+ unknown,self(),Comment),
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
+ Comment,undefined);
+ Loc1 ->
+ {Mod,Func} = get_mf(Loc1),
+ %% call end_per_testcase on a separate process, only so
+ %% that the user has a chance to clean up after init_per_testcase,
+ %% even after abortion
+ NewCurrConf =
+ case CurrConf of
+ {{Mod,Func},Conf} ->
+ TVal = case lists:keysearch(default_timeout,1,Conf) of
+ {value,{default_timeout,Tmo}} -> Tmo;
+ _ -> ?DEFAULT_TIMETRAP_SECS*1000
+ end,
+ EndConfPid =
+ call_end_conf(Mod,Func,Pid,ErrorMsg,
+ Loc1,
+ [{tc_status,{failed,ErrorMsg}}|Conf],
+ TVal),
+ {EndConfPid,{Mod,Func},Conf};
+ _ ->
+ spawn_fw_call(Mod,Func,Pid,ErrorMsg,
+ Loc1,self(),Comment),
+ undefined
+ end,
+ run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,
+ Comment,NewCurrConf)
+ end;
killed ->
%% result of an exit(TestCase,kill) call, which is the
%% only way to abort a testcase process that traps exits
@@ -920,6 +947,7 @@ spawn_fw_call(Mod,{init_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
{TVal/1000,Skip,Loc,[],Comment}}
end,
spawn_link(FwCall);
+
spawn_fw_call(Mod,{end_per_testcase,Func},Pid,{timetrap_timeout,TVal}=Why,
Loc,SendTo,_Comment) ->
FwCall =
diff --git a/lib/test_server/src/test_server_sup.erl b/lib/test_server/src/test_server_sup.erl
index 2b4e1efb71..625724fbb5 100644
--- a/lib/test_server/src/test_server_sup.erl
+++ b/lib/test_server/src/test_server_sup.erl
@@ -504,6 +504,7 @@ framework_call(Callback,Func,Args,DefaultReturn) ->
end,
case erlang:function_exported(Mod,Func,length(Args)) of
true ->
+ put(test_server_loc, {Mod,Func,framework}),
EH = fun(Reason) -> exit({fw_error,{Mod,Func,Reason}}) end,
try apply(Mod,Func,Args) of
Result ->