diff options
Diffstat (limited to 'lib/common_test/src')
-rw-r--r-- | lib/common_test/src/ct.erl | 79 | ||||
-rw-r--r-- | lib/common_test/src/ct_framework.erl | 4 | ||||
-rw-r--r-- | lib/common_test/src/ct_hooks.erl | 21 | ||||
-rw-r--r-- | lib/common_test/src/ct_logs.erl | 28 |
4 files changed, 93 insertions, 39 deletions
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index 69e15fa246..d72b8bc0e1 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -63,7 +63,7 @@ log/1, log/2, log/3, print/1, print/2, print/3, pal/1, pal/2, pal/3, - fail/1, comment/1, + fail/1, fail/2, comment/1, comment/2, testcases/2, userdata/2, userdata/3, timetrap/1, sleep/1]). @@ -108,7 +108,7 @@ install(Opts) -> %%% Cases = atom() | [atom()] %%% Result = [TestResult] | {error,Reason} %%% -%%% @doc Run the given testcase(s). +%%% @doc Run the given test case(s). %%% %%% <p>Requires that <code>ct:install/1</code> has been run first.</p> %%% @@ -121,7 +121,7 @@ run(TestDir,Suite,Cases) -> %%%----------------------------------------------------------------- %%% @spec run(TestDir,Suite) -> Result %%% -%%% @doc Run all testcases in the given suite. +%%% @doc Run all test cases in the given suite. %%% @see run/3. run(TestDir,Suite) -> ct_run:run(TestDir,Suite). @@ -130,7 +130,7 @@ run(TestDir,Suite) -> %%% @spec run(TestDirs) -> Result %%% TestDirs = TestDir | [TestDir] %%% -%%% @doc Run all testcases in all suites in the given directories. +%%% @doc Run all test cases in all suites in the given directories. %%% @see run/3. run(TestDirs) -> ct_run:run(TestDirs). @@ -440,11 +440,10 @@ log(X1,X2) -> %%% Format = string() %%% Args = list() %%% -%%% @doc Printout from a testcase to the log. +%%% @doc Printout from a test case to the log file. %%% -%%% <p>This function is meant for printing stuff directly from a -%%% testcase (i.e. not from within the CT framework) in the test -%%% log.</p> +%%% <p>This function is meant for printing a string directly from a +%%% test case to the test case log file.</p> %%% %%% <p>Default <code>Category</code> is <code>default</code> and %%% default <code>Args</code> is <code>[]</code>.</p> @@ -473,10 +472,10 @@ print(X1,X2) -> %%% Format = string() %%% Args = list() %%% -%%% @doc Printout from a testcase to the console. +%%% @doc Printout from a test case to the console. %%% -%%% <p>This function is meant for printing stuff from a testcase on -%%% the console.</p> +%%% <p>This function is meant for printing a string from a test case +%%% to the console.</p> %%% %%% <p>Default <code>Category</code> is <code>default</code> and %%% default <code>Args</code> is <code>[]</code>.</p> @@ -508,10 +507,10 @@ pal(X1,X2) -> %%% Format = string() %%% Args = list() %%% -%%% @doc Print and log from a testcase. +%%% @doc Print and log from a test case. %%% -%%% <p>This function is meant for printing stuff from a testcase both -%%% in the log and on the console.</p> +%%% <p>This function is meant for printing a string from a test case, +%%% both to the test case log file and to the console.</p> %%% %%% <p>Default <code>Category</code> is <code>default</code> and %%% default <code>Args</code> is <code>[]</code>.</p> @@ -528,18 +527,35 @@ pal(Category,Format,Args) -> fail(Reason) -> exit({test_case_failed,Reason}). + +%%%----------------------------------------------------------------- +%%% @spec fail(Format, Args) -> void() +%%% Format = string() +%%% Args = list() +%%% +%%% @doc Terminate a test case with an error message specified +%%% by a format string and a list of values (used as arguments to +%%% <code>io_lib:format/2</code>). +fail(Format, Args) -> + try io_lib:format(Format, Args) of + Str -> + exit({test_case_failed,lists:flatten(Str)}) + catch + _:BadArgs -> + exit({BadArgs,{?MODULE,fail,[Format,Args]}}) + end. + + %%%----------------------------------------------------------------- %%% @spec comment(Comment) -> void() %%% Comment = term() %%% -%%% @doc Print the given <code>Comment</code> in the comment field of +%%% @doc Print the given <code>Comment</code> in the comment field in %%% the table on the test suite result page. %%% %%% <p>If called several times, only the last comment is printed. -%%% <code>comment/1</code> is also overwritten by the return value -%%% <code>{comment,Comment}</code> or by the function -%%% <code>fail/1</code> (which prints <code>Reason</code> as a -%%% comment).</p> +%%% The test case return value <code>{comment,Comment}</code> +%%% overwrites the string set by this function.</p> comment(Comment) when is_list(Comment) -> Formatted = case (catch io_lib:format("~s",[Comment])) of @@ -553,6 +569,29 @@ comment(Comment) -> Formatted = io_lib:format("~p",[Comment]), send_html_comment(lists:flatten(Formatted)). +%%%----------------------------------------------------------------- +%%% @spec comment(Format, Args) -> void() +%%% Format = string() +%%% Args = list() +%%% +%%% @doc Print the formatted string in the comment field in +%%% the table on the test suite result page. +%%% +%%% <p>The <code>Format</code> and <code>Args</code> arguments are +%%% used in call to <code>io_lib:format/2</code> in order to create +%%% the comment string. The behaviour of <code>comment/2</code> is +%%% otherwise the same as the <code>comment/1</code> function (see +%%% above for details).</p> +comment(Format, Args) when is_list(Format), is_list(Args) -> + Formatted = + case (catch io_lib:format(Format, Args)) of + {'EXIT',Reason} -> % bad args + exit({Reason,{?MODULE,comment,[Format,Args]}}); + String -> + lists:flatten(String) + end, + send_html_comment(Formatted). + send_html_comment(Comment) -> Html = "<font color=\"green\">" ++ Comment ++ "</font>", ct_util:set_testdata({comment,Html}), @@ -606,7 +645,7 @@ listenv(Telnet) -> %%% Testcases = list() %%% Reason = term() %%% -%%% @doc Returns all testcases in the specified suite. +%%% @doc Returns all test cases in the specified suite. testcases(TestDir, Suite) -> case make_and_load(TestDir, Suite) of E = {error,_} -> diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 0897675591..ee0162c5e3 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -1274,6 +1274,10 @@ report(What,Data) -> tests_done -> ok; tc_start -> + %% Data = {{Suite,Func},LogFileName} + ct_event:sync_notify(#event{name=tc_logfile, + node=node(), + data=Data}), ok; tc_done -> {_Suite,Case,Result} = Data, diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl index ffafc582cf..c42adbbdd9 100644 --- a/lib/common_test/src/ct_hooks.erl +++ b/lib/common_test/src/ct_hooks.erl @@ -178,8 +178,9 @@ call_generic(#ct_hook_config{ module = Mod, state = State} = Hook, call(Fun, Config, Meta) -> maybe_lock(), Hooks = get_hooks(), - Res = call(get_new_hooks(Config, Fun) ++ - [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks], + Calls = get_new_hooks(Config, Fun) ++ + [{HookId,Fun} || #ct_hook_config{id = HookId} <- Hooks], + Res = call(resort(Calls,Hooks,Meta), remove(?config_name,Config), Meta, Hooks), maybe_unlock(), Res. @@ -205,7 +206,7 @@ call([{Hook, call_id, NextFun} | Rest], Config, Meta, Hooks) -> {Hooks ++ [NewHook], [{NewId, call_init}, {NewId,NextFun} | Rest]} end, - call(resort(NewRest,NewHooks), Config, Meta, NewHooks) + call(resort(NewRest,NewHooks,Meta), Config, Meta, NewHooks) catch Error:Reason -> Trace = erlang:get_stacktrace(), ct_logs:log("Suite Hook","Failed to start a CTH: ~p:~p", @@ -221,7 +222,7 @@ call([{HookId, Fun} | Rest], Config, Meta, Hooks) -> {NewConf, NewHook} = Fun(Hook, Config, Meta), NewCalls = get_new_hooks(NewConf, Fun), NewHooks = lists:keyreplace(HookId, #ct_hook_config.id, Hooks, NewHook), - call(resort(NewCalls ++ Rest,NewHooks), %% Resort if call_init changed prio + call(resort(NewCalls ++ Rest,NewHooks,Meta), %% Resort if call_init changed prio remove(?config_name, NewConf), Meta, terminate_if_scope_ends(HookId, Meta, NewHooks)) catch throw:{error_in_cth_call,Reason} -> @@ -308,6 +309,18 @@ get_hooks() -> %% call_id < call_init < ctfirst < Priority 1 < .. < Priority N < ctlast %% If Hook Priority is equal, check when it has been installed and %% sort on that instead. +%% If we are doing a cleanup call i.e. {post,pre}_end_per_*, all priorities +%% are reversed. Probably want to make this sorting algorithm pluginable +%% as some point... +resort(Calls,Hooks,[F|_R]) when F == post_end_per_testcase; + F == pre_end_per_group; + F == post_end_per_group; + F == pre_end_per_suite; + F == post_end_per_suite -> + lists:reverse(resort(Calls,Hooks)); +resort(Calls,Hooks,_Meta) -> + resort(Calls,Hooks). + resort(Calls, Hooks) -> lists:sort( fun({_,_,_},_) -> diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index d66a31d9a5..19ad7b26d8 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -223,7 +223,6 @@ init_tc(RefreshLog) -> %%% %%% <p>This function is called by ct_framework:end_tc/3</p> end_tc(TCPid) -> - io:format(xhtml("<br>", "<br />")), %% use call here so that the TC process will wait and receive %% possible exit signals from ct_logs before end_tc returns ok call({end_tc,TCPid}). @@ -745,20 +744,19 @@ print_style(Fd,StyleSheet) -> 0 -> string:str(Str,"<STYLE>"); N0 -> N0 end, - case Pos0 of - 0 -> print_style_error(Fd,StyleSheet,missing_style_tag); - _ -> - Pos1 = case string:str(Str,"</style>") of - 0 -> string:str(Str,"</STYLE>"); - N1 -> N1 - end, - case Pos1 of - 0 -> - print_style_error(Fd,StyleSheet,missing_style_end_tag); - _ -> - Style = string:sub_string(Str,Pos0,Pos1+7), - io:format(Fd,"~s\n",[Style]) - end + Pos1 = case string:str(Str,"</style>") of + 0 -> string:str(Str,"</STYLE>"); + N1 -> N1 + end, + if (Pos0 == 0) and (Pos1 /= 0) -> + print_style_error(Fd,StyleSheet,missing_style_start_tag); + (Pos0 /= 0) and (Pos1 == 0) -> + print_style_error(Fd,StyleSheet,missing_style_end_tag); + Pos0 /= 0 -> + Style = string:sub_string(Str,Pos0,Pos1+7), + io:format(Fd,"~s\n",[Style]); + Pos0 == 0 -> + io:format(Fd,"<style>~s</style>\n",[Str]) end; {error,Reason} -> print_style_error(Fd,StyleSheet,Reason) |