aboutsummaryrefslogtreecommitdiffstats
path: root/lib/common_test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common_test')
-rw-r--r--lib/common_test/doc/src/notes.xml118
-rw-r--r--lib/common_test/priv/Makefile.in6
-rw-r--r--lib/common_test/src/Makefile8
-rw-r--r--lib/common_test/src/ct.erl4
-rw-r--r--lib/common_test/src/ct_config.erl8
-rw-r--r--lib/common_test/src/ct_config_plain.erl4
-rw-r--r--lib/common_test/src/ct_conn_log_h.erl33
-rw-r--r--lib/common_test/src/ct_event.erl4
-rw-r--r--lib/common_test/src/ct_framework.erl27
-rw-r--r--lib/common_test/src/ct_gen_conn.erl4
-rw-r--r--lib/common_test/src/ct_groups.erl4
-rw-r--r--lib/common_test/src/ct_hooks.erl6
-rw-r--r--lib/common_test/src/ct_logs.erl145
-rw-r--r--lib/common_test/src/ct_make.erl8
-rw-r--r--lib/common_test/src/ct_master.erl45
-rw-r--r--lib/common_test/src/ct_master_event.erl6
-rw-r--r--lib/common_test/src/ct_master_logs.erl24
-rw-r--r--lib/common_test/src/ct_master_status.erl4
-rw-r--r--lib/common_test/src/ct_netconfc.erl40
-rw-r--r--lib/common_test/src/ct_run.erl30
-rw-r--r--lib/common_test/src/ct_telnet.erl32
-rw-r--r--lib/common_test/src/ct_telnet_client.erl4
-rw-r--r--lib/common_test/src/ct_testspec.erl4
-rw-r--r--lib/common_test/src/ct_util.erl10
-rw-r--r--lib/common_test/src/cth_conn_log.erl7
-rw-r--r--lib/common_test/src/cth_surefire.erl4
-rw-r--r--lib/common_test/src/unix_telnet.erl4
-rw-r--r--lib/common_test/test/ct_error_SUITE.erl65
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/config_restored_SUITE.erl175
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl239
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_master_SUITE.erl3
-rw-r--r--lib/common_test/test/ct_master_SUITE_data/master/master_SUITE.erl2
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE.erl5
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl7
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/ns.erl21
-rw-r--r--lib/common_test/test/ct_surefire_SUITE.erl77
-rw-r--r--lib/common_test/test/ct_test_support.erl6
-rw-r--r--lib/common_test/vsn.mk2
39 files changed, 943 insertions, 254 deletions
diff --git a/lib/common_test/doc/src/notes.xml b/lib/common_test/doc/src/notes.xml
index 8c3b13951d..030de2efa9 100644
--- a/lib/common_test/doc/src/notes.xml
+++ b/lib/common_test/doc/src/notes.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2004</year><year>2012</year>
+ <year>2004</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -32,6 +32,122 @@
<file>notes.xml</file>
</header>
+<section><title>Common_Test 1.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Severe errors detected by <c>test_server</c> (e.g. if log
+ files directories cannot be created) will now be reported
+ to <c>common_test</c> and noted in the <c>common_test</c>
+ logs.</p>
+ <p>
+ Own Id: OTP-9769 Aux Id: kunagi-202 [113] </p>
+ </item>
+ <item>
+ <p>
+ If a busy test case generated lots of error messages,
+ cth_log_redirect:post_end_per_testcase would crash with a
+ timeout while waiting for the error logger to finish
+ handling all error reports. The default timer was 5
+ seconds. This has now been extended to 5 minutes.</p>
+ <p>
+ Own Id: OTP-10040 Aux Id: kunagi-173 [84] </p>
+ </item>
+ <item>
+ <p>
+ Some bugfixes in <c>ct_snmp:</c></p>
+ <p>
+ <list> <item> ct_snmp will now use the value of the
+ 'agent_vsns' config variable when setting the 'variables'
+ parameter to snmp application agent configuration.
+ Earlier this had to be done separately - i.e. the
+ supported versions had to be specified twice. </item>
+ <item> Snmp application failed to write notify.conf since
+ ct_snmp gave the notify type as a string instead of an
+ atom. This has been corrected. </item> </list></p>
+ <p>
+ Own Id: OTP-10432</p>
+ </item>
+ <item>
+ <p>
+ Some bugfixes in <c>ct_snmp</c>:</p>
+ <p>
+ <list> <item> Functions <c>register_users/2</c>,
+ <c>register_agents/2</c> and <c>register_usm_users/2</c>,
+ and the corresponding <c>unregister_*/1</c> functions
+ were not executable. These are corrected/rewritten.
+ </item> <item> Function <c>update_usm_users/2</c> is
+ removed, and an unregister function is added instead.
+ Update can now be done with unregister_usm_users and then
+ register_usm_users. </item> <item> Functions
+ <c>unregister_*/2</c> are added, so specific
+ users/agents/usm users can be unregistered. </item>
+ <item> Function <c>unload_mibs/1</c> is added for
+ completeness. </item> <item> Overriding configuration
+ files did not work, since the files were written in
+ priv_dir instead of in the configuration dir
+ (priv_dir/conf). This has been corrected. </item> <item>
+ Arguments to <c>register_usm_users/2</c> were faulty
+ documented. This has been corrected. </item> </list></p>
+ <p>
+ Own Id: OTP-10434 Aux Id: kunagi-264 [175] </p>
+ </item>
+ <item>
+ <p>
+ Faulty exported specs in common test has been corrected
+ to <c>ct_netconfc:hook_options/0</c> and
+ <c>inet:hostname/0</c></p>
+ <p>
+ Own Id: OTP-10601</p>
+ </item>
+ <item>
+ <p>
+ The netconf client in common_test did not adjust the
+ window after receiving data. Due to this, the client
+ stopped receiving data after a while. This has been
+ corrected.</p>
+ <p>
+ Own Id: OTP-10646</p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Known Bugs and Problems</title>
+ <list>
+ <item>
+ <p>
+ The earlier undocumented cross cover feature for
+ accumulating cover data over multiple tests has now been
+ fixed and documented.</p>
+ <p>
+ Own Id: OTP-9870 Aux Id: kunagi-206 [117] </p>
+ </item>
+ <item>
+ <p>
+ CT drops error reason when groups/0 crashes.</p>
+ <p>
+ Own Id: OTP-10631 Aux Id: kunagi-345 [256] </p>
+ </item>
+ <item>
+ <p>
+ Problem opening sftp connection with ct_ssh.</p>
+ <p>
+ Own Id: OTP-10632 Aux Id: kunagi-346 [257] </p>
+ </item>
+ <item>
+ <p>
+ Event handler on a ct_master node causes hanging.</p>
+ <p>
+ Own Id: OTP-10634 Aux Id: kunagi-347 [258] </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Common_Test 1.6.3.1</title>
<section><title>Known Bugs and Problems</title>
diff --git a/lib/common_test/priv/Makefile.in b/lib/common_test/priv/Makefile.in
index 4372ab124e..5a9fabbe45 100644
--- a/lib/common_test/priv/Makefile.in
+++ b/lib/common_test/priv/Makefile.in
@@ -68,15 +68,15 @@ JS = jquery-latest.js jquery.tablesorter.min.js
include ../../test_server/vsn.mk
debug opt:
- sed -e 's;@CT_VSN@;$(VSN);' \
+ $(V_at)sed -e 's;@CT_VSN@;$(VSN);' \
-e 's;@TS_VSN@;$(TEST_SERVER_VSN);' \
../install.sh.in > install.sh
- chmod 775 install.sh
+ $(V_at)chmod 775 install.sh
docs:
clean:
- rm -f $(SCRIPTS)
+ $(V_at)rm -f $(SCRIPTS)
# ----------------------------------------------------
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index dd2923ece9..4600c0ad78 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2003-2012. All Rights Reserved.
+# Copyright Ericsson AB 2003-2013. 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
@@ -97,7 +97,7 @@ DTD_FILES = \
# ----------------------------------------------------
ERL_COMPILE_FLAGS += -pa ../ebin -I../include -I $(ERL_TOP)/lib/snmp/include/ \
-I../../test_server/include -I../../xmerl/inc/ \
- -I $(ERL_TOP)/lib/kernel/include
+ -I $(ERL_TOP)/lib/kernel/include -Werror
# ----------------------------------------------------
# Targets
@@ -127,10 +127,10 @@ clean:
# Special Build Targets
# ----------------------------------------------------
$(APP_TARGET): $(APP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
$(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk
- sed -e 's;%VSN%;$(VSN);' $< > $@
+ $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@
# ----------------------------------------------------
# Release Target
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index 853a1582cf..04a95a53fa 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. 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
@@ -735,7 +735,7 @@ fail(Format, Args) ->
%%% overwrites the string set by this function.</p>
comment(Comment) when is_list(Comment) ->
Formatted =
- case (catch io_lib:format("~s",[Comment])) of
+ case (catch io_lib:format("~ts",[Comment])) of
{'EXIT',_} -> % it's a list not a string
io_lib:format("~p",[Comment]);
String ->
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index ac4ffbb236..c35cbd3c08 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. 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
@@ -610,7 +610,7 @@ encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) ->
EncBin = crypto:des3_cbc_encrypt(K1, K2, K3, IVec, Bin2),
case file:write_file(EncryptFileName, EncBin) of
ok ->
- io:format("~s --(encrypt)--> ~s~n",
+ io:format("~ts --(encrypt)--> ~ts~n",
[SrcFileName,EncryptFileName]),
ok;
{error,Reason} ->
@@ -652,7 +652,7 @@ decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) ->
_ ->
case file:write_file(TargetFileName, SrcBin) of
ok ->
- io:format("~s --(decrypt)--> ~s~n",
+ io:format("~ts --(decrypt)--> ~ts~n",
[EncryptFileName,TargetFileName]),
ok;
{error,Reason} ->
@@ -703,7 +703,7 @@ get_crypt_key_from_file() ->
_ ->
case catch string:tokens(binary_to_list(Result), [$\n,$\r]) of
[Key] ->
- io:format("~nCrypt key file: ~s~n", [FullName]),
+ io:format("~nCrypt key file: ~ts~n", [FullName]),
Key;
_ ->
{error,{bad_crypt_file,FullName}}
diff --git a/lib/common_test/src/ct_config_plain.erl b/lib/common_test/src/ct_config_plain.erl
index 237df5c8f3..c6547f0a40 100644
--- a/lib/common_test/src/ct_config_plain.erl
+++ b/lib/common_test/src/ct_config_plain.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. 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
@@ -47,7 +47,7 @@ read_config(ConfigFile) ->
{error,no_crypt_file} ->
{error,{config_file_error,
lists:flatten(
- io_lib:format("~s",[file:format_error(Reason)]))}};
+ io_lib:format("~ts",[file:format_error(Reason)]))}};
{error,CryptError} ->
{error,{decrypt_file_error,CryptError}};
_ when is_list(Key) ->
diff --git a/lib/common_test/src/ct_conn_log_h.erl b/lib/common_test/src/ct_conn_log_h.erl
index d7bd18606b..ac08a3e0ad 100644
--- a/lib/common_test/src/ct_conn_log_h.erl
+++ b/lib/common_test/src/ct_conn_log_h.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2013. 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
@@ -52,7 +52,7 @@ open_files([],State) ->
do_open_files([{Tag,File}|Logs],Acc) ->
- case file:open(File, [write]) of
+ case file:open(File, [write,{encoding,utf8}]) of
{ok,Fd} ->
do_open_files(Logs,[{Tag,Fd}|Acc]);
{error,Reason} ->
@@ -98,9 +98,9 @@ terminate(_,#state{logs=Logs}) ->
%%% Writing reports
write_report(Time,#conn_log{module=ConnMod}=Info,Data,State) ->
{LogType,Fd} = get_log(Info,State),
- io:format(Fd,"~n~s~s~s",[format_head(ConnMod,LogType,Time),
- format_title(LogType,Info),
- format_data(ConnMod,LogType,Data)]).
+ io:format(Fd,"~n~ts~ts~ts",[format_head(ConnMod,LogType,Time),
+ format_title(LogType,Info),
+ format_data(ConnMod,LogType,Data)]).
write_error(Time,#conn_log{module=ConnMod}=Info,Report,State) ->
case get_log(Info,State) of
@@ -109,9 +109,10 @@ write_error(Time,#conn_log{module=ConnMod}=Info,Report,State) ->
%% sasl error handler, so don't write it again.
ok;
{LogType,Fd} ->
- io:format(Fd,"~n~s~s~s",[format_head(ConnMod,LogType,Time," ERROR"),
- format_title(LogType,Info),
- format_error(LogType,Report)])
+ io:format(Fd,"~n~ts~ts~ts",
+ [format_head(ConnMod,LogType,Time," ERROR"),
+ format_title(LogType,Info),
+ format_error(LogType,Report)])
end.
get_log(Info,State) ->
@@ -140,16 +141,16 @@ format_head(ConnMod,LogType,Time) ->
format_head(ConnMod,LogType,Time,"").
format_head(ConnMod,raw,Time,Text) ->
- io_lib:format("~n~p, ~p~s, ",[now_to_time(Time),ConnMod,Text]);
+ io_lib:format("~n~w, ~w~ts, ",[now_to_time(Time),ConnMod,Text]);
format_head(ConnMod,_,Time,Text) ->
Head = pad_char_end(?WIDTH,pretty_head(now_to_time(Time),ConnMod,Text),$=),
- io_lib:format("~n~s",[Head]).
+ io_lib:format("~n~ts",[Head]).
format_title(raw,#conn_log{client=Client}=Info) ->
- io_lib:format("Client ~p ~s ~s",[Client,actionstr(Info),serverstr(Info)]);
+ io_lib:format("Client ~w ~s ~ts",[Client,actionstr(Info),serverstr(Info)]);
format_title(_,Info) ->
Title = pad_char_end(?WIDTH,pretty_title(Info),$=),
- io_lib:format("~n~s", [Title]).
+ io_lib:format("~n~ts", [Title]).
format_data(_,_,NoData) when NoData == ""; NoData == <<>> ->
"";
@@ -162,8 +163,6 @@ format_error(pretty,Report) ->
[io_lib:format("~n ~p: ~p",[K,V]) || {K,V} <- Report].
-
-
%%%-----------------------------------------------------------------
%%% Helpers
conn_info(LoggingProc, #conn_log{client=undefined} = ConnInfo) ->
@@ -187,12 +186,12 @@ now_to_time({_,_,MicroS}=Now) ->
pretty_head({{{Y,Mo,D},{H,Mi,S}},MicroS},ConnMod,Text0) ->
Text = string:to_upper(atom_to_list(ConnMod) ++ Text0),
- io_lib:format("= ~s ==== ~s-~s-~p::~s:~s:~s,~s ",
+ io_lib:format("= ~s ==== ~s-~s-~w::~s:~s:~s,~s ",
[Text,t(D),month(Mo),Y,t(H),t(Mi),t(S),
micro2milli(MicroS)]).
pretty_title(#conn_log{client=Client}=Info) ->
- io_lib:format("= Client ~p ~s Server ~s ",
+ io_lib:format("= Client ~w ~s Server ~ts ",
[Client,actionstr(Info),serverstr(Info)]).
actionstr(#conn_log{action=send}) -> "----->";
@@ -204,7 +203,7 @@ actionstr(_) -> "<---->".
serverstr(#conn_log{name=undefined,address=Address}) ->
io_lib:format("~p",[Address]);
serverstr(#conn_log{name=Alias,address=Address}) ->
- io_lib:format("~p(~p)",[Alias,Address]).
+ io_lib:format("~w(~p)",[Alias,Address]).
month(1) -> "Jan";
month(2) -> "Feb";
diff --git a/lib/common_test/src/ct_event.erl b/lib/common_test/src/ct_event.erl
index 49e0635d79..c1c1d943b9 100644
--- a/lib/common_test/src/ct_event.erl
+++ b/lib/common_test/src/ct_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. 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
@@ -150,7 +150,7 @@ init(RecvPids) ->
%%--------------------------------------------------------------------
handle_event(Event,State=#state{receivers=RecvPids}) ->
print("~n=== ~w ===~n", [?MODULE]),
- print("~p: ~p~n", [Event#event.name,Event#event.data]),
+ print("~w: ~w~n", [Event#event.name,Event#event.data]),
lists:foreach(fun(Recv) -> report_event(Recv,Event) end, RecvPids),
{ok,State}.
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index c1abf27e9f..5fe4eaf511 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. 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
@@ -750,12 +750,12 @@ error_notification(Mod,Func,_Args,{Error,Loc}) ->
Descr1 = lists:flatten(io_lib:format("~P",[Descr,10])),
if length(Descr1) > 50 ->
Descr2 = string:substr(Descr1,1,50),
- io_lib:format("{badmatch,~s...}",[Descr2]);
+ io_lib:format("{badmatch,~ts...}",[Descr2]);
true ->
- io_lib:format("{badmatch,~s}",[Descr1])
+ io_lib:format("{badmatch,~ts}",[Descr1])
end;
{test_case_failed,Reason} ->
- case (catch io_lib:format("{test_case_failed,~s}", [Reason])) of
+ case (catch io_lib:format("{test_case_failed,~ts}", [Reason])) of
{'EXIT',_} ->
io_lib:format("{test_case_failed,~p}", [Reason]);
Result -> Result
@@ -788,7 +788,7 @@ error_notification(Mod,Func,_Args,{Error,Loc}) ->
"<font color=\"green\">" ++ "(" ++ "</font>"
++ Comment ++
"<font color=\"green\">" ++ ")" ++ "</font>",
- Str = io_lib:format("~s ~s", [ErrorHtml,CommentHtml]),
+ Str = io_lib:format("~ts ~ts", [ErrorHtml,CommentHtml]),
test_server:comment(Str)
end
end,
@@ -803,24 +803,24 @@ error_notification(Mod,Func,_Args,{Error,Loc}) ->
end,
case Loc of
[{?MODULE,error_in_suite}] ->
- PrintErr("Error in suite detected: ~s", [ErrStr]);
+ PrintErr("Error in suite detected: ~ts", [ErrStr]);
R when R == unknown; R == undefined ->
- PrintErr("Error detected: ~s", [ErrStr]);
+ PrintErr("Error detected: ~ts", [ErrStr]);
%% if a function specified by all/0 does not exist, we
%% pick up undef here
[{LastMod,LastFunc}|_] when ErrStr == "undef" ->
- PrintErr("~w:~w could not be executed~nReason: ~s",
+ PrintErr("~w:~w could not be executed~nReason: ~ts",
[LastMod,LastFunc,ErrStr]);
[{LastMod,LastFunc}|_] ->
- PrintErr("~w:~w failed~nReason: ~s", [LastMod,LastFunc,ErrStr]);
+ PrintErr("~w:~w failed~nReason: ~ts", [LastMod,LastFunc,ErrStr]);
[{LastMod,LastFunc,LastLine}|_] ->
%% print error to console, we are only
%% interested in the last executed expression
- PrintErr("~w:~w failed on line ~w~nReason: ~s",
+ PrintErr("~w:~w failed on line ~w~nReason: ~ts",
[LastMod,LastFunc,LastLine,ErrStr]),
case ct_util:read_suite_data({seq,Mod,Func}) of
@@ -1184,7 +1184,7 @@ report(What,Data) ->
ok;
{error,Reason} ->
ct_logs:log("COVER INFO",
- "Importing cover data from: ~s fails! "
+ "Importing cover data from: ~ts fails! "
"Reason: ~p", [Imp,Reason])
end
end, Imps)
@@ -1349,4 +1349,7 @@ format_comment(Comment) ->
%%%-----------------------------------------------------------------
%%% @spec get_html_wrapper(TestName, PrintLabel, Cwd) -> Header
get_html_wrapper(TestName, PrintLabel, Cwd, TableCols) ->
- ct_logs:get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols).
+ get_html_wrapper(TestName, PrintLabel, Cwd, TableCols, utf8).
+
+get_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) ->
+ ct_logs:get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding).
diff --git a/lib/common_test/src/ct_gen_conn.erl b/lib/common_test/src/ct_gen_conn.erl
index 1f01d84601..2d4b1d1f52 100644
--- a/lib/common_test/src/ct_gen_conn.erl
+++ b/lib/common_test/src/ct_gen_conn.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. 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
@@ -272,7 +272,7 @@ call(Pid, Msg, Timeout) ->
after Timeout ->
erlang:demonitor(MRef, [flush]),
log("ct_gen_conn",
- "Connection process ~p not responding. Killing now!",
+ "Connection process ~w not responding. Killing now!",
[Pid]),
exit(Pid, kill),
{error,{process_down,Pid,forced_termination}}
diff --git a/lib/common_test/src/ct_groups.erl b/lib/common_test/src/ct_groups.erl
index 74ab5e5439..14a8aab881 100644
--- a/lib/common_test/src/ct_groups.erl
+++ b/lib/common_test/src/ct_groups.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. 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
@@ -462,7 +462,7 @@ make_conf(Mod, Name, Props, TestSpec) ->
false ->
ct_logs:log("TEST INFO", "init_per_group/2 and "
"end_per_group/2 missing for group "
- "~p in ~p, using default.",
+ "~w in ~w, using default.",
[Name,Mod]),
{{ct_framework,init_per_group},
{ct_framework,end_per_group},
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index 1bcc63738e..3d87a82e24 100644
--- a/lib/common_test/src/ct_hooks.erl
+++ b/lib/common_test/src/ct_hooks.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. 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
@@ -362,11 +362,11 @@ catch_apply(M,F,A, Default) ->
[{M,F,A,_}|_] when Reason == undef ->
Default;
Trace ->
- ct_logs:log("Suite Hook","Call to CTH failed: ~p:~p",
+ ct_logs:log("Suite Hook","Call to CTH failed: ~w:~p",
[error,{Reason,Trace}]),
throw({error_in_cth_call,
lists:flatten(
- io_lib:format("~p:~p/~p CTH call failed",
+ io_lib:format("~w:~w/~w CTH call failed",
[M,F,length(A)]))})
end
end.
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index 0b7a8bb075..5924930072 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. 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
@@ -35,9 +35,10 @@
-export([add_external_logs/1, add_link/3]).
-export([make_last_run_index/0]).
-export([make_all_suites_index/1,make_all_runs_index/1]).
--export([get_ts_html_wrapper/4]).
+-export([get_ts_html_wrapper/5]).
-export([xhtml/2, locate_priv_file/1, make_relative/1]).
-export([insert_javascript/1]).
+-export([uri/1]).
%% Logging stuff directly from testcase
-export([tc_log/3, tc_log/4, tc_log_async/3, tc_print/3, tc_print/4,
@@ -307,8 +308,8 @@ end_log() ->
%%% calling test suite.</p>
add_external_logs(Logs) ->
start_log("External Logs"),
- [cont_log("<a href=~p>~s</a>\n",
- [filename:join("log_private",Log),Log]) || Log <- Logs],
+ [cont_log("<a href=\"~ts\">~ts</a>\n",
+ [uri(filename:join("log_private",Log)),Log]) || Log <- Logs],
end_log().
%%%-----------------------------------------------------------------
@@ -320,8 +321,8 @@ add_external_logs(Logs) ->
%%% @doc Print a link to a given file stored in the priv_dir of the
%%% calling test suite.
add_link(Heading,File,Type) ->
- log(Heading,"<a href=~p type=~p>~s</a>\n",
- [filename:join("log_private",File),Type,File]).
+ log(Heading,"<a href=\"~ts\" type=~p>~ts</a>\n",
+ [uri(filename:join("log_private",File)),Type,File]).
%%%-----------------------------------------------------------------
@@ -469,7 +470,7 @@ ct_log(Category,Format,Args) ->
%%%=================================================================
%%% Internal functions
int_header() ->
- "<div class=\"ct_internal\"><b>*** CT ~s *** ~s</b>".
+ "<div class=\"ct_internal\"><b>*** CT ~s *** ~ts</b>".
int_footer() ->
"</div>".
@@ -692,7 +693,7 @@ logger_loop(State) ->
logger_loop(State);
{set_stylesheet,TC,SSFile} ->
Fd = State#logger_state.ct_log_fd,
- io:format(Fd, "~p loading external style sheet: ~s~n",
+ io:format(Fd, "~p loading external style sheet: ~ts~n",
[TC,SSFile]),
logger_loop(State#logger_state{stylesheet = SSFile});
{clear_stylesheet,_} when State#logger_state.stylesheet == undefined ->
@@ -752,7 +753,7 @@ print_to_log(sync, FromPid, TCGL, List, State) ->
IoProc = if FromPid /= TCGL -> TCGL;
true -> State#logger_state.ct_log_fd
end,
- io:format(IoProc, "~s", [lists:foldl(IoFun, [], List)]),
+ io:format(IoProc, "~ts", [lists:foldl(IoFun, [], List)]),
State;
print_to_log(async, FromPid, TCGL, List, State) ->
@@ -764,7 +765,7 @@ print_to_log(async, FromPid, TCGL, List, State) ->
end,
Printer = fun() ->
test_server:permit_io(IoProc, self()),
- io:format(IoProc, "~s", [lists:foldl(IoFun, [], List)])
+ io:format(IoProc, "~ts", [lists:foldl(IoFun, [], List)])
end,
case State#logger_state.async_print_jobs of
[] ->
@@ -868,7 +869,7 @@ set_evmgr_gl(GL) ->
end.
open_ctlog() ->
- {ok,Fd} = file:open(?ct_log_name,[write]),
+ {ok,Fd} = file:open(?ct_log_name,[write,{encoding,utf8}]),
io:format(Fd, header("Common Test Framework Log", {[],[1,2],[]}), []),
case file:consult(ct_run:variables_file_name("../")) of
{ok,Vars} ->
@@ -878,7 +879,7 @@ open_ctlog() ->
Dir = filename:dirname(Cwd),
Variables = ct_run:variables_file_name(Dir),
io:format(Fd,
- "Can not read the file \'~s\' Reason: ~w\n"
+ "Can not read the file \'~ts\' Reason: ~w\n"
"No configuration found for test!!\n",
[Variables,Reason])
end,
@@ -904,7 +905,7 @@ print_style(Fd,undefined) ->
print_style(Fd,StyleSheet) ->
case file:read_file(StyleSheet) of
{ok,Bin} ->
- Str = binary_to_list(Bin),
+ Str = b2s(Bin,encoding(StyleSheet)),
Pos0 = case string:str(Str,"<style>") of
0 -> string:str(Str,"<STYLE>");
N0 -> N0
@@ -919,9 +920,9 @@ print_style(Fd,StyleSheet) ->
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]);
+ io:format(Fd,"~ts\n",[Style]);
Pos0 == 0 ->
- io:format(Fd,"<style>~s</style>\n",[Str])
+ io:format(Fd,"<style>~ts</style>\n",[Str])
end;
{error,Reason} ->
print_style_error(Fd,StyleSheet,Reason)
@@ -934,7 +935,7 @@ print_style(Fd,StyleSheet) ->
%% [StyleSheet]).
print_style_error(Fd,StyleSheet,Reason) ->
- io:format(Fd,"\n<!-- Failed to load stylesheet ~s: ~p -->\n",
+ io:format(Fd,"\n<!-- Failed to load stylesheet ~ts: ~p -->\n",
[StyleSheet,Reason]),
print_style(Fd,undefined).
@@ -963,7 +964,7 @@ make_last_run_index(StartTime) ->
% io:put_chars("done\n"),
ok;
Err ->
- io:format("Unknown internal error while updating ~s. "
+ io:format("Unknown internal error while updating ~ts. "
"Please report.\n(Err: ~p, ID: 1)",
[AbsIndexName,Err]),
{error, Err}
@@ -1001,7 +1002,7 @@ make_last_run_index1(StartTime,IndexName) ->
%% write current Totals to file, later to be used in all_runs log
write_totals_file(?totals_name,Label,Logs1,Totals),
Index = [Index0|index_footer()],
- case force_write_file(IndexName, Index) of
+ case force_write_file(IndexName, unicode:characters_to_binary(Index)) of
ok ->
ok;
{error, Reason} ->
@@ -1085,7 +1086,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
CrashDumpName = SuiteName ++ "_erl_crash.dump",
case filelib:is_file(CrashDumpName) of
true ->
- ["&nbsp;<a href=\"", CrashDumpName,
+ ["&nbsp;<a href=\"", uri(CrashDumpName),
"\">(CrashDump)</a>"];
false ->
""
@@ -1115,10 +1116,10 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
[] -> "none";
_ -> "<a href=\""++?all_runs_name++"\">Old Runs</a>"
end,
- A = xhtml(["<td><font size=\"-1\"><a href=\"",CtLogFile,
+ A = xhtml(["<td><font size=\"-1\"><a href=\"",uri(CtLogFile),
"\">CT Log</a></font></td>\n",
"<td><font size=\"-1\">",OldRunsLink,"</font></td>\n"],
- ["<td><a href=\"",CtLogFile,"\">CT Log</a></td>\n",
+ ["<td><a href=\"",uri(CtLogFile),"\">CT Log</a></td>\n",
"<td>",OldRunsLink,"</td>\n"]),
{L,T,N,A};
false ->
@@ -1128,7 +1129,8 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
if NotBuilt == 0 ->
["<td align=right>",integer_to_list(NotBuilt),"</td>\n"];
true ->
- ["<td align=right><a href=\"",filename:join(CtRunDir,?ct_log_name),"\">",
+ ["<td align=right><a href=\"",
+ uri(filename:join(CtRunDir,?ct_log_name)),"\">",
integer_to_list(NotBuilt),"</a></td>\n"]
end,
FailStr =
@@ -1151,7 +1153,7 @@ make_one_index_entry1(SuiteName, Link, Label, Success, Fail, UserSkip, AutoSkip,
[xhtml("<tr valign=top>\n",
["<tr class=\"",odd_or_even(),"\">\n"]),
xhtml("<td><font size=\"-1\"><a href=\"", "<td><a href=\""),
- LogFile,"\">",SuiteName,"</a>", CrashDumpLink,
+ uri(LogFile),"\">",SuiteName,"</a>", CrashDumpLink,
xhtml("</font></td>\n", "</td>\n"),
Lbl, Timestamp,
"<td align=right>",integer_to_list(Success),"</td>\n",
@@ -1364,8 +1366,9 @@ header1(Title, SubTitle, TableCols) ->
"<head>\n",
"<title>" ++ Title ++ " " ++ SubTitle ++ "</title>\n",
"<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n",
xhtml("",
- ["<link rel=\"stylesheet\" href=\"",CSSFile,"\" type=\"text/css\">\n"]),
+ ["<link rel=\"stylesheet\" href=\"",uri(CSSFile),"\" type=\"text/css\">\n"]),
xhtml("",
["<script type=\"text/javascript\" src=\"",JQueryFile,
"\"></script>\n"]),
@@ -1462,7 +1465,7 @@ count_cases(Dir) ->
LogFile = filename:join(Dir, ?suitelog_name),
case file:read_file(LogFile) of
{ok, Bin} ->
- case count_cases1(binary_to_list(Bin),
+ case count_cases1(b2s(Bin),
{undefined,undefined,undefined,undefined}) of
{error,not_complete} ->
%% The test is not complete - dont write summary
@@ -1557,7 +1560,7 @@ config_table1([{Key,Value}|Vars]) ->
"<td><pre>",io_lib:format("~p",[Value]),"</pre></td></tr>\n"],
["<tr class=\"", odd_or_even(), "\">\n",
"<td>", atom_to_list(Key), "</td>\n",
- "<td>", io_lib:format("~p",[Value]), "</td>\n</tr>\n"]) |
+ "<td>", io_lib:format("~p",[Value]), "</td>\n</tr>\n"]) |
config_table1(Vars)];
config_table1([]) ->
["</tbody>\n</table>\n"].
@@ -1574,8 +1577,9 @@ make_all_runs_index(When) ->
DirsSorted = (catch sort_all_runs(Dirs)),
Header = all_runs_header(),
Index = [runentry(Dir) || Dir <- DirsSorted],
- Result = file:write_file(AbsName,Header++Index++
- all_runs_index_footer()),
+ Result = file:write_file(AbsName,
+ unicode:characters_to_binary(
+ Header++Index++all_runs_index_footer())),
if When == start -> ok;
true -> io:put_chars("done\n")
end,
@@ -1602,10 +1606,27 @@ sort_all_runs(Dirs) ->
interactive_link() ->
[Dir|_] = lists:reverse(filelib:wildcard(logdir_prefix()++"*.*")),
CtLog = filename:join(Dir,"ctlog.html"),
- Body = ["Log from last interactive run: <a href=\"",CtLog,"\">",
- timestamp(Dir),"</a>"],
- file:write_file("last_interactive.html",Body),
- io:format("~n~nUpdated ~s\n"
+ Body =
+ [xhtml(
+ ["<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n",
+ "<html>\n"],
+ ["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n",
+ "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n",
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"]),
+ "<!-- autogenerated by '"++atom_to_list(?MODULE)++"' -->\n",
+ "<head>\n",
+ "<title>Last interactive run</title>\n",
+ "<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n",
+ "</head>\n",
+ "<body>\n",
+ "Log from last interactive run: <a href=\"",uri(CtLog),"\">",
+ timestamp(Dir),"</a>",
+ "</body>\n",
+ "</html>\n"
+ ],
+ file:write_file("last_interactive.html",unicode:characters_to_binary(Body)),
+ io:format("~n~nUpdated ~ts\n"
"Any CT activities will be logged here\n",
[?abs("last_interactive.html")]).
@@ -1655,7 +1676,7 @@ runentry(Dir) ->
TestNames;
true ->
Trunc = Polish(string:substr(TestNames,1,?testname_width-3)),
- lists:flatten(io_lib:format("~s...",[Trunc]))
+ lists:flatten(io_lib:format("~ts...",[Trunc]))
end,
Total = TotSucc+TotFail+AllSkip,
A = xhtml(["<td align=center><font size=\"-1\">",Node,
@@ -1695,7 +1716,7 @@ runentry(Dir) ->
"<td align=right>?</td>\n"],
A++B++C
end,
- Index = filename:join(Dir,?index_name),
+ Index = uri(filename:join(Dir,?index_name)),
[xhtml("<tr>\n", ["<tr class=\"",odd_or_even(),"\">\n"]),
xhtml(["<td><font size=\"-1\"><a href=\"",Index,"\">",timestamp(Dir),"</a>",
TotalsStr,"</font></td>\n"],
@@ -1836,7 +1857,7 @@ make_all_suites_index(NewTestData = {_TestName,DirName}) ->
ok ->
ok;
Err ->
- io:format("Unknown internal error while updating ~s. "
+ io:format("Unknown internal error while updating ~ts. "
"Please report.\n(Err: ~p, ID: 1)",
[AbsIndexName,Err]),
{error, Err}
@@ -1900,7 +1921,7 @@ make_all_suites_index1(When, AbsIndexName, AllLogDirs) ->
ok
end;
Err ->
- io:format("Unknown internal error while updating ~s. "
+ io:format("Unknown internal error while updating ~ts. "
"Please report.\n(Err: ~p, ID: 1)",
[AbsIndexName,Err]),
{error, Err}
@@ -1912,7 +1933,7 @@ make_all_suites_index2(IndexName, AllTestLogDirs) ->
all_suites_index_header(),
0, 0, 0, 0, 0, [], []),
Index = [Index0|index_footer()],
- case force_write_file(IndexName, Index) of
+ case force_write_file(IndexName, unicode:characters_to_binary(Index)) of
ok ->
{ok,CacheData};
{error, Reason} ->
@@ -1970,7 +1991,7 @@ make_all_suites_ix_cached(AbsIndexName, NewTestData, Label, AllTestLogDirs) ->
all_suites_index_header(IndexDir),
0, 0, 0, 0, 0),
Index = [Index0|index_footer()],
- case force_write_file(AbsIndexName, Index) of
+ case force_write_file(AbsIndexName, unicode:characters_to_binary(Index)) of
ok ->
ok;
{error, Reason} ->
@@ -2116,7 +2137,7 @@ simulate_logger_loop() ->
receive
{log,_,_,_,_,_,List} ->
S = [[io_lib:format(Str,Args),io_lib:nl()] || {Str,Args} <- List],
- io:format("~s",[S]),
+ io:format("~ts",[S]),
simulate_logger_loop();
stop ->
ok
@@ -2273,11 +2294,12 @@ make_relative1(DirTs, CwdTs) ->
Ups ++ DirTs.
%%%-----------------------------------------------------------------
-%%% @spec get_ts_html_wrapper(TestName, PrintLabel, Cwd) -> {Mode,Header,Footer}
+%%% @spec get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding)
+%%% -> {Mode,Header,Footer}
%%%
%%% @doc
%%%
-get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) ->
+get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols, Encoding) ->
TestName1 = if is_list(TestName) ->
lists:flatten(TestName);
true ->
@@ -2319,14 +2341,16 @@ get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) ->
"<html>\n",
"<head><title>", TestName1, "</title>\n",
"<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=",
+ html_encoding(Encoding),"\">\n",
"</head>\n",
"<body", Bgr, " bgcolor=\"white\" text=\"black\" ",
"link=\"blue\" vlink=\"purple\" alink=\"red\">\n",
LabelStr, "\n"],
["<center>\n<br><hr><p>\n",
- "<a href=\"", AllRuns,
+ "<a href=\"", uri(AllRuns),
"\">Test run history\n</a> | ",
- "<a href=\"", TestIndex,
+ "<a href=\"", uri(TestIndex),
"\">Top level test index\n</a>\n</p>\n",
Copyright,"</center>\n</body>\n</html>\n"]};
_ ->
@@ -2363,14 +2387,15 @@ get_ts_html_wrapper(TestName, PrintLabel, Cwd, TableCols) ->
"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n",
"<head>\n<title>", TestName1, "</title>\n",
"<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
- "<link rel=\"stylesheet\" href=\"", CSSFile, "\" type=\"text/css\">\n",
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n",
+ "<link rel=\"stylesheet\" href=\"", uri(CSSFile), "\" type=\"text/css\">\n",
"<script type=\"text/javascript\" src=\"", JQueryFile, "\"></script>\n",
"<script type=\"text/javascript\" src=\"", TableSorterFile, "\"></script>\n"] ++
TableSorterScript ++ ["</head>\n","<body>\n", LabelStr, "\n"],
["<center>\n<br /><hr /><p>\n",
- "<a href=\"", AllRuns,
+ "<a href=\"", uri(AllRuns),
"\">Test run history\n</a> | ",
- "<a href=\"", TestIndex,
+ "<a href=\"", uri(TestIndex),
"\">Top level test index\n</a>\n</p>\n",
Copyright,"</center>\n</body>\n</html>\n"]}
end.
@@ -2460,3 +2485,31 @@ insert_javascript({tablesorter,TableName,
" $(\"#",TableName,"\").trigger(\"update\");\n",
" $(\"#",TableName,"\").trigger(\"appendCache\");\n",
"});\n</script>\n"].
+
+uri("") ->
+ "";
+uri(Href) ->
+ test_server_ctrl:uri_encode(Href).
+
+%% Read magic comment to get encoding of text file.
+%% If no magic comment exists, assume default encoding
+encoding(File) ->
+ case epp:read_encoding(File) of
+ none ->
+ epp:default_encoding();
+ E ->
+ E
+ end.
+
+%% Convert binary to string using default encoding
+b2s(Bin) ->
+ b2s(Bin,epp:default_encoding()).
+
+%% Convert binary to string using given encoding
+b2s(Bin,Encoding) ->
+ unicode:characters_to_list(Bin,Encoding).
+
+html_encoding(latin1) ->
+ "iso-8859-1";
+html_encoding(utf8) ->
+ "utf-8".
diff --git a/lib/common_test/src/ct_make.erl b/lib/common_test/src/ct_make.erl
index 8ddb91d355..d4bd81e78d 100644
--- a/lib/common_test/src/ct_make.erl
+++ b/lib/common_test/src/ct_make.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2011. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2013. 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
@@ -280,13 +280,13 @@ recompile(File, NoExec, Load, Opts) ->
do_recompile(_File, true, _Load, _Opts) ->
out_of_date;
do_recompile(File, false, noload, Opts) ->
- io:format("Recompile: ~s\n",[File]),
+ io:format("Recompile: ~ts\n",[File]),
compile:file(File, [report_errors, report_warnings, error_summary |Opts]);
do_recompile(File, false, load, Opts) ->
- io:format("Recompile: ~s\n",[File]),
+ io:format("Recompile: ~ts\n",[File]),
c:c(File, Opts);
do_recompile(File, false, netload, Opts) ->
- io:format("Recompile: ~s\n",[File]),
+ io:format("Recompile: ~ts\n",[File]),
c:nc(File, Opts).
exists(File) ->
diff --git a/lib/common_test/src/ct_master.erl b/lib/common_test/src/ct_master.erl
index d58395b692..e516f635d2 100644
--- a/lib/common_test/src/ct_master.erl
+++ b/lib/common_test/src/ct_master.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. 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
@@ -256,7 +256,7 @@ run_all([],AllLogDirs,_,AllEvHs,_AllIncludes,
{value,{_,Dir}} -> Dir;
false -> "."
end,
- log(tty,"Master Logdir","~s",[MasterLogDir]),
+ log(tty,"Master Logdir","~ts",[MasterLogDir]),
start_master(lists:reverse(NodeOpts),Handlers,MasterLogDir,
LogDirs,InitOptions,Specs),
ok.
@@ -347,7 +347,7 @@ init_master(Parent,NodeOptsList,EvHandlers,MasterLogDir,LogDirs,
SpecsStr = lists:map(fun(Name) ->
Name ++ " "
end,Specs),
- ct_master_logs:log("Test Specification file(s)","~s",
+ ct_master_logs:log("Test Specification file(s)","~ts",
[lists:flatten(SpecsStr)])
end,
@@ -356,7 +356,7 @@ init_master(Parent,NodeOptsList,EvHandlers,MasterLogDir,LogDirs,
ct_master_event:add_handler(),
%% add user handlers for master event manager
Add = fun({H,Args}) ->
- log(all,"Adding Event Handler","~p",[H]),
+ log(all,"Adding Event Handler","~w",[H]),
case gen_event:add_handler(?CT_MEVMGR_REF,H,Args) of
ok -> ok;
{'EXIT',Why} -> exit(Why);
@@ -408,7 +408,7 @@ init_master2(Parent,NodeOptsList,LogDirs) ->
SpawnAndMon =
fun({Node,Opts}) ->
monitor_node(Node,true),
- log(all,"Test Info","Starting test(s) on ~p...",[Node]),
+ log(all,"Test Info","Starting test(s) on ~w...",[Node]),
{spawn_link(Node,?MODULE,init_node_ctrl,[self(),Cookie,Opts]),
Node}
end,
@@ -422,7 +422,7 @@ master_loop(#state{node_ctrl_pids=[],
results=Finished}) ->
Str =
lists:map(fun({Node,Result}) ->
- io_lib:format("~-40.40.*s~p\n",
+ io_lib:format("~-40.40.*ts~p\n",
[$_,atom_to_list(Node),Result])
end,lists:reverse(Finished)),
log(all,"TEST RESULTS",Str,[]),
@@ -469,7 +469,7 @@ master_loop(State=#state{node_ctrl_pids=NodeCtrlPids,
undefined ->
%% ignore (but report) exit from master_logger etc
log(all,"Test Info",
- "Warning! Process ~p has terminated. Reason: ~p",
+ "Warning! Process ~w has terminated. Reason: ~p",
[Pid,Reason]),
master_loop(State)
end;
@@ -552,7 +552,7 @@ update_queue(take,Node,From,Lock={Op,Resource},Locks,Blocked) ->
%% Blocked: [{{Operation,Resource},Node,WaitingPid},...]
case lists:keysearch(Lock,1,Locks) of
{value,{_Lock,Owner}} -> % other node has lock
- log(html,"Lock Info","Node ~p blocked on ~w by ~w. Resource: ~p",
+ log(html,"Lock Info","Node ~w blocked on ~w by ~w. Resource: ~p",
[Node,Op,Owner,Resource]),
Blocked1 = Blocked ++ [{Lock,Node,From}],
{Locks,Blocked1};
@@ -567,7 +567,7 @@ update_queue(release,Node,_From,Lock={Op,Resource},Locks,Blocked) ->
case lists:keysearch(Lock,1,Blocked) of
{value,E={Lock,SomeNode,WaitingPid}} ->
Blocked1 = lists:delete(E,Blocked),
- log(html,"Lock Info","Node ~p proceeds with ~w. Resource: ~p",
+ log(html,"Lock Info","Node ~w proceeds with ~w. Resource: ~p",
[SomeNode,Op,Resource]),
reply(ok,WaitingPid), % waiting process may start
{Locks1,Blocked1};
@@ -646,7 +646,8 @@ refresh_logs([D|Dirs],Refreshed) ->
refresh_logs([],Refreshed) ->
Str =
lists:map(fun({D,Result}) ->
- io_lib:format("Refreshing logs in ~p... ~p",[D,Result])
+ io_lib:format("Refreshing logs in ~p... ~p",
+ [D,Result])
end,Refreshed),
log(all,"Info",Str,[]).
@@ -659,7 +660,7 @@ init_node_ctrl(MasterPid,Cookie,Opts) ->
process_flag(trap_exit, true),
MasterNode = node(MasterPid),
group_leader(whereis(user),self()),
- io:format("~n********** node_ctrl process ~p started on ~p **********~n",
+ io:format("~n********** node_ctrl process ~w started on ~w **********~n",
[self(),node()]),
%% initially this node must have the same cookie as the master node
%% but now we set it explicitly for the connection so that test suites
@@ -692,7 +693,7 @@ init_node_ctrl(MasterPid,Cookie,Opts) ->
pong ->
MasterPid ! {self(),{result,Result}};
pang ->
- io:format("Warning! Connection to master node ~p is lost. "
+ io:format("Warning! Connection to master node ~w is lost. "
"Can't report result!~n~n", [MasterNode])
end.
@@ -773,24 +774,24 @@ start_nodes(InitOptions)->
IsAlive = lists:member(NodeName, nodes()),
case {HasNodeStart, IsAlive} of
{false, false}->
- io:format("WARNING: Node ~p is not alive but has no "
+ io:format("WARNING: Node ~w is not alive but has no "
"node_start option~n", [NodeName]);
{false, true}->
- io:format("Node ~p is alive~n", [NodeName]);
+ io:format("Node ~w is alive~n", [NodeName]);
{true, false}->
{node_start, NodeStart} = lists:keyfind(node_start, 1, Options),
{value, {callback_module, Callback}, NodeStart2}=
lists:keytake(callback_module, 1, NodeStart),
case Callback:start(Host, Node, NodeStart2) of
{ok, NodeName} ->
- io:format("Node ~p started successfully "
- "with callback ~p~n", [NodeName,Callback]);
+ io:format("Node ~w started successfully "
+ "with callback ~w~n", [NodeName,Callback]);
{error, Reason, _NodeName} ->
- io:format("Failed to start node ~p with callback ~p! "
+ io:format("Failed to start node ~w with callback ~w! "
"Reason: ~p~n", [NodeName, Callback, Reason])
end;
{true, true}->
- io:format("WARNING: Node ~p is alive but has node_start "
+ io:format("WARNING: Node ~w is alive but has node_start "
"option~n", [NodeName])
end
end,
@@ -804,8 +805,8 @@ eval_on_nodes(InitOptions)->
{false,_}->
ok;
{true,false}->
- io:format("WARNING: Node ~p is not alive but has eval "
- "option ~n", [NodeName]);
+ io:format("WARNING: Node ~w is not alive but has eval "
+ "option~n", [NodeName]);
{true,true}->
{eval, MFAs} = lists:keyfind(eval, 1, Options),
evaluate(NodeName, MFAs)
@@ -816,10 +817,10 @@ eval_on_nodes(InitOptions)->
evaluate(Node, [{M,F,A}|MFAs])->
case rpc:call(Node, M, F, A) of
{badrpc,Reason}->
- io:format("WARNING: Failed to call ~p:~p/~p on node ~p "
+ io:format("WARNING: Failed to call ~w:~w/~w on node ~w "
"due to ~p~n", [M,F,length(A),Node,Reason]);
Result->
- io:format("Called ~p:~p/~p on node ~p, result: ~p~n",
+ io:format("Called ~w:~w/~w on node ~w, result: ~p~n",
[M,F,length(A),Node,Result])
end,
evaluate(Node, MFAs);
diff --git a/lib/common_test/src/ct_master_event.erl b/lib/common_test/src/ct_master_event.erl
index a70baefaaf..5877b7c6f2 100644
--- a/lib/common_test/src/ct_master_event.erl
+++ b/lib/common_test/src/ct_master_event.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. 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
@@ -114,13 +114,13 @@ init(_) ->
%% each installed event handler to handle the event.
%%--------------------------------------------------------------------
handle_event(#event{name=start_logging,node=Node,data=RunDir},State) ->
- ct_master_logs:log("CT Master Event Handler","Got ~s from ~p",[RunDir,Node]),
+ ct_master_logs:log("CT Master Event Handler","Got ~ts from ~w",[RunDir,Node]),
ct_master_logs:nodedir(Node,RunDir),
{ok,State};
handle_event(#event{name=Name,node=Node,data=Data},State) ->
print("~n=== ~w ===~n", [?MODULE]),
- print("~p on ~p: ~p~n", [Name,Node,Data]),
+ print("~w on ~w: ~p~n", [Name,Node,Data]),
{ok,State}.
%%--------------------------------------------------------------------
diff --git a/lib/common_test/src/ct_master_logs.erl b/lib/common_test/src/ct_master_logs.erl
index 84f175c0a9..5393097f57 100644
--- a/lib/common_test/src/ct_master_logs.erl
+++ b/lib/common_test/src/ct_master_logs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. 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
@@ -133,7 +133,7 @@ init(Parent,LogDir,Nodes) ->
end,Nodes)),
io:format(CtLogFd,int_header(),[log_timestamp(now()),"Test Nodes\n"]),
- io:format(CtLogFd,"~s\n",[NodeStr]),
+ io:format(CtLogFd,"~ts\n",[NodeStr]),
io:put_chars(CtLogFd,[int_footer(),"\n"]),
NodeDirIxFd = open_nodedir_index(RunDirAbs,Time),
@@ -201,7 +201,7 @@ loop(State) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
open_ct_master_log(Dir) ->
FullName = filename:join(Dir,?ct_master_log_name),
- {ok,Fd} = file:open(FullName,[write]),
+ {ok,Fd} = file:open(FullName,[write,{encoding,utf8}]),
io:put_chars(Fd,header("Common Test Master Log", {[],[1,2],[]})),
%% maybe add config info here later
io:put_chars(Fd,config_table([])),
@@ -235,7 +235,7 @@ config_table1([]) ->
["</tbody>\n</table>\n"].
int_header() ->
- "<div class=\"ct_internal\"><b>*** CT MASTER ~s *** ~s</b>".
+ "<div class=\"ct_internal\"><b>*** CT MASTER ~s *** ~ts</b>".
int_footer() ->
"</div>".
@@ -244,7 +244,7 @@ int_footer() ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
open_nodedir_index(Dir,StartTime) ->
FullName = filename:join(Dir,?nodedir_index_name),
- {ok,Fd} = file:open(FullName,[write]),
+ {ok,Fd} = file:open(FullName,[write,{encoding,utf8}]),
io:put_chars(Fd,nodedir_index_header(StartTime)),
Fd.
@@ -253,7 +253,8 @@ print_nodedir(Node,RunDir,Fd) ->
io:put_chars(Fd,
["<tr>\n"
"<td align=center>",atom_to_list(Node),"</td>\n",
- "<td align=left><a href=\"",Index,"\">",Index,"</a></td>\n",
+ "<td align=left><a href=\"",ct_logs:uri(Index),"\">",Index,
+ "</a></td>\n",
"</tr>\n"]),
ok.
@@ -283,7 +284,9 @@ make_all_runs_index(LogDir) ->
DirsSorted = (catch sort_all_runs(Dirs)),
Header = all_runs_header(),
Index = [runentry(Dir) || Dir <- DirsSorted],
- Result = file:write_file(FullName,Header++Index++index_footer()),
+ Result = file:write_file(FullName,
+ unicode:characters_to_binary(
+ Header++Index++index_footer())),
Result.
sort_all_runs(Dirs) ->
@@ -323,7 +326,8 @@ runentry(Dir) ->
end,
Index = filename:join(Dir,?nodedir_index_name),
["<tr>\n"
- "<td align=center><a href=\"",Index,"\">",timestamp(Dir),"</a></td>\n",
+ "<td align=center><a href=\"",ct_logs:uri(Index),"\">",
+ timestamp(Dir),"</a></td>\n",
"<td align=center>",MasterStr,"</td>\n",
"<td align=center>",NodesStr,"</td>\n",
"</tr>\n"].
@@ -381,8 +385,10 @@ header(Title, TableCols) ->
"<head>\n",
"<title>" ++ Title ++ "</title>\n",
"<meta http-equiv=\"cache-control\" content=\"no-cache\">\n",
+ "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">\n",
xhtml("",
- ["<link rel=\"stylesheet\" href=\"",CSSFile,"\" type=\"text/css\">"]),
+ ["<link rel=\"stylesheet\" href=\"",ct_logs:uri(CSSFile),
+ "\" type=\"text/css\">"]),
xhtml("",
["<script type=\"text/javascript\" src=\"",JQueryFile,
"\"></script>\n"]),
diff --git a/lib/common_test/src/ct_master_status.erl b/lib/common_test/src/ct_master_status.erl
index 76060fb7bb..f9f511ecca 100644
--- a/lib/common_test/src/ct_master_status.erl
+++ b/lib/common_test/src/ct_master_status.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. 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
@@ -70,7 +70,7 @@ init(_) ->
%%
handle_event(#event{name=Name,node=Node,data=Data},State) ->
print("~n=== ~w ===~n", [?MODULE]),
- print("~p on ~p: ~p~n", [Name,Node,Data]),
+ print("~w on ~w: ~p~n", [Name,Node,Data]),
{ok,State}.
%%--------------------------------------------------------------------
diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl
index 1ccbc86d8f..1339e53780 100644
--- a/lib/common_test/src/ct_netconfc.erl
+++ b/lib/common_test/src/ct_netconfc.erl
@@ -1,7 +1,7 @@
%%----------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2013. 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
@@ -1281,10 +1281,11 @@ do_send(Connection, SimpleXml) ->
to_xml_doc(Simple) ->
Prolog = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
- Xml = list_to_binary(xmerl:export_simple([Simple],
- xmerl_xml,
- [#xmlAttribute{name=prolog,
- value=Prolog}])),
+ Xml = unicode:characters_to_binary(
+ xmerl:export_simple([Simple],
+ xmerl_xml,
+ [#xmlAttribute{name=prolog,
+ value=Prolog}])),
<<Xml/binary,?END_TAG/binary>>.
%%%-----------------------------------------------------------------
@@ -1688,18 +1689,27 @@ log(#connection{host=Host,port=Port,name=Name},Action,Data) ->
%% Log callback - called from the error handler process
-format_data(raw,Data) ->
- io_lib:format("~n~s~n",[hide_password(Data)]);
-format_data(pretty,Data) ->
- io_lib:format("~n~s~n",[indent(Data)]);
-format_data(html,Data) ->
- io_lib:format("~n~s~n",[html_format(Data)]).
+format_data(How,Data) ->
+ %% Assuming that the data is encoded as UTF-8. If it is not, then
+ %% the printout might be wrong, but the format function will not
+ %% crash!
+ %% FIXME: should probably read encoding from the data and do
+ %% unicode:characters_to_binary(Data,InEncoding,utf8) when calling
+ %% log/3 instead of assuming utf8 in as done here!
+ do_format_data(How,unicode:characters_to_binary(Data)).
+
+do_format_data(raw,Data) ->
+ io_lib:format("~n~ts~n",[hide_password(Data)]);
+do_format_data(pretty,Data) ->
+ io_lib:format("~n~ts~n",[indent(Data)]);
+do_format_data(html,Data) ->
+ io_lib:format("~n~ts~n",[html_format(Data)]).
%%%-----------------------------------------------------------------
%%% Hide password elements from XML data
hide_password(Bin) ->
re:replace(Bin,<<"(<password[^>]*>)[^<]*(</password>)">>,<<"\\1*****\\2">>,
- [global,{return,binary}]).
+ [global,{return,binary},unicode]).
%%%-----------------------------------------------------------------
%%% HTML formatting
@@ -1717,13 +1727,13 @@ indent(Bin) ->
Part ->
indent1(lists:reverse(Part)++String,erase(indent))
end,
- list_to_binary(IndentedString).
+ unicode:characters_to_binary(IndentedString).
%% Normalizes the XML document by removing all space and newline
%% between two XML tags.
%% Returns a list, no matter if the input was a list or a binary.
-normalize(Str) ->
- re:replace(Str,<<">[ \r\n\t]+<">>,<<"><">>,[global,{return,list}]).
+normalize(Bin) ->
+ re:replace(Bin,<<">[ \r\n\t]+<">>,<<"><">>,[global,{return,list},unicode]).
indent1("<?"++Rest1,Indent1) ->
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 742e287493..c0bdbb2a09 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. 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
@@ -148,7 +148,7 @@ script_start(Args) ->
_ -> ""
end
end,
- io:format("~nCommon Test~s starting (cwd is ~s)~n~n",
+ io:format("~nCommon Test~s starting (cwd is ~ts)~n~n",
[CTVsn,Cwd]),
Self = self(),
Pid = spawn_link(fun() -> script_start1(Self, Args) end),
@@ -378,7 +378,7 @@ run_or_refresh(Opts = #opts{logdir = LogDir}, Args) ->
{error,{all_suites_index,ASReason}};
_ ->
file:set_cwd(Cwd),
- io:format("Logs in ~s refreshed!~n~n",
+ io:format("Logs in ~ts refreshed!~n~n",
[LogDir1]),
timer:sleep(500), % time to flush io before quitting
ok
@@ -881,7 +881,7 @@ run_test1(StartOpts) when is_list(StartOpts) ->
undefined ->
Tracing = start_trace(StartOpts),
{ok,Cwd} = file:get_cwd(),
- io:format("~nCommon Test starting (cwd is ~s)~n~n", [Cwd]),
+ io:format("~nCommon Test starting (cwd is ~ts)~n~n", [Cwd]),
Res =
case ct_repeat:loop_test(func, StartOpts) of
false ->
@@ -1320,7 +1320,7 @@ run_testspec(TestSpec) ->
run_testspec1(TestSpec) ->
{ok,Cwd} = file:get_cwd(),
- io:format("~nCommon Test starting (cwd is ~s)~n~n", [Cwd]),
+ io:format("~nCommon Test starting (cwd is ~ts)~n~n", [Cwd]),
case catch run_testspec2(TestSpec) of
{'EXIT',Reason} ->
file:set_cwd(Cwd),
@@ -1457,7 +1457,7 @@ refresh_logs(LogDir) ->
{error,{all_runs_index,ARReason}};
_ ->
file:set_cwd(Cwd),
- io:format("Logs in ~s refreshed!~n",[LogDir]),
+ io:format("Logs in ~ts refreshed!~n",[LogDir]),
ok
end
end
@@ -1780,7 +1780,7 @@ possibly_spawn(true, Tests, Skip, Opts) ->
end,
unlink(CTUtilSrv),
SupPid = spawn(Supervisor),
- io:format(user, "~nTest control handed over to process ~p~n~n",
+ io:format(user, "~nTest control handed over to process ~w~n~n",
[SupPid]),
SupPid.
@@ -1868,7 +1868,7 @@ verify_suites(TestSuites) ->
Suite)),
io:format(user,
"Suite ~w not found"
- "in directory ~s~n",
+ "in directory ~ts~n",
[Suite,TestDir]),
{Found,[{DS,[Name]}|NotFound]}
end
@@ -1883,7 +1883,7 @@ verify_suites(TestSuites) ->
ActualDir = filename:dirname(SuiteFile),
{[{ActualDir,Suite}|Found],NotFound};
false ->
- io:format(user, "Directory ~s is "
+ io:format(user, "Directory ~ts is "
"invalid~n", [Dir]),
Name = filename:join(Dir, atom_to_list(Suite)),
{Found,[{DS,[Name]}|NotFound]}
@@ -2123,7 +2123,7 @@ do_run_test(Tests, Skip, Opts) ->
cross = CovCross,
src = _CovSrc}} ->
ct_logs:log("COVER INFO",
- "Using cover specification file: ~s~n"
+ "Using cover specification file: ~ts~n"
"App: ~w~n"
"Cross cover: ~w~n"
"Including ~w modules~n"
@@ -2138,7 +2138,7 @@ do_run_test(Tests, Skip, Opts) ->
DelResult = file:delete(CovExport),
ct_logs:log("COVER INFO",
"Warning! "
- "Export file ~s already exists. "
+ "Export file ~ts already exists. "
"Deleting with result: ~p",
[CovExport,DelResult]);
false ->
@@ -2620,7 +2620,7 @@ log_ts_names(Specs) ->
List = lists:map(fun(Name) ->
Name ++ " "
end, Specs),
- ct_logs:log("Test Specification file(s)", "~s",
+ ct_logs:log("Test Specification file(s)", "~ts",
[lists:flatten(List)]).
merge_arguments(Args) ->
@@ -2731,10 +2731,10 @@ event_handler_args2opts(Default, Args) ->
event_handler_init_args2opts(EHs)
end.
event_handler_init_args2opts([EH, Arg, "and" | EHs]) ->
- [{list_to_atom(EH),lists:flatten(io_lib:format("~s",[Arg]))} |
+ [{list_to_atom(EH),lists:flatten(io_lib:format("~ts",[Arg]))} |
event_handler_init_args2opts(EHs)];
event_handler_init_args2opts([EH, Arg]) ->
- [{list_to_atom(EH),lists:flatten(io_lib:format("~s",[Arg]))}];
+ [{list_to_atom(EH),lists:flatten(io_lib:format("~ts",[Arg]))}];
event_handler_init_args2opts([]) ->
[].
@@ -3056,7 +3056,7 @@ start_trace(Args) ->
false
end;
{_,Error} ->
- io:format("Warning! Tracing not started. Reason: ~s~n~n",
+ io:format("Warning! Tracing not started. Reason: ~ts~n~n",
[file:format_error(Error)]),
false
end;
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index b13c050e32..02186864a5 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. 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
@@ -201,7 +201,7 @@ open(KeyOrName,ConnType,TargetMod,Extra) ->
close(Connection) ->
case get_handle(Connection) of
{ok,Pid} ->
- log("ct_telnet:close","Handle: ~p",[Pid]),
+ log("ct_telnet:close","Handle: ~w",[Pid]),
case ct_gen_conn:stop(Pid) of
{error,{process_down,Pid,noproc}} ->
{error,already_closed};
@@ -558,7 +558,7 @@ reconnect(Ip,Port,N,State=#state{target_mod=TargetMod,
Error when N==0 ->
Error;
_Error ->
- log("Reconnect failed!","Retries left: ~p",[N]),
+ log("Reconnect failed!","Retries left: ~w",[N]),
timer:sleep(ReconnInt),
reconnect(Ip,Port,N-1,State)
end.
@@ -567,7 +567,7 @@ reconnect(Ip,Port,N,State=#state{target_mod=TargetMod,
%% @hidden
terminate(TelnPid,State) ->
log(heading(terminate,State#state.name),
- "Closing telnet connection.\nId: ~p",
+ "Closing telnet connection.\nId: ~w",
[TelnPid]),
ct_telnet_client:close(TelnPid).
@@ -899,7 +899,7 @@ one_expect(Data,Pattern,EO) ->
[Prompt] when Prompt==prompt; Prompt=={prompt,PromptType} ->
%% Only searching for prompt
log_lines(UptoPrompt),
- try_cont_log("<b>PROMPT:</b> ~s", [PromptType]),
+ try_cont_log("<b>PROMPT:</b> ~ts", [PromptType]),
{match,{prompt,PromptType},Rest};
[{prompt,_OtherPromptType}] ->
%% Only searching for one specific prompt, not thisone
@@ -969,7 +969,7 @@ seq_expect1(Data,[prompt|Patterns],Acc,Rest,EO) ->
{continue,[prompt|Patterns],Acc,LastLine};
PromptType ->
log_lines(Data),
- try_cont_log("<b>PROMPT:</b> ~s", [PromptType]),
+ try_cont_log("<b>PROMPT:</b> ~ts", [PromptType]),
seq_expect(Rest,Patterns,[{prompt,PromptType}|Acc],EO)
end;
seq_expect1(Data,[{prompt,PromptType}|Patterns],Acc,Rest,EO) ->
@@ -980,7 +980,7 @@ seq_expect1(Data,[{prompt,PromptType}|Patterns],Acc,Rest,EO) ->
{continue,[{prompt,PromptType}|Patterns],Acc,LastLine};
PromptType ->
log_lines(Data),
- try_cont_log("<b>PROMPT:</b> ~s", [PromptType]),
+ try_cont_log("<b>PROMPT:</b> ~ts", [PromptType]),
seq_expect(Rest,Patterns,[{prompt,PromptType}|Acc],EO);
_OtherPromptType ->
log_lines(Data),
@@ -1032,13 +1032,13 @@ match_line(Line,Patterns,FoundPrompt,EO) ->
match_line(Line,[prompt|Patterns],false,EO,RetTag) ->
match_line(Line,Patterns,false,EO,RetTag);
match_line(Line,[prompt|_Patterns],FoundPrompt,_EO,RetTag) ->
- try_cont_log(" ~s", [Line]),
- try_cont_log("<b>PROMPT:</b> ~s", [FoundPrompt]),
+ try_cont_log(" ~ts", [Line]),
+ try_cont_log("<b>PROMPT:</b> ~ts", [FoundPrompt]),
{RetTag,{prompt,FoundPrompt}};
match_line(Line,[{prompt,PromptType}|_Patterns],FoundPrompt,_EO,RetTag)
when PromptType==FoundPrompt ->
- try_cont_log(" ~s", [Line]),
- try_cont_log("<b>PROMPT:</b> ~s", [FoundPrompt]),
+ try_cont_log(" ~ts", [Line]),
+ try_cont_log("<b>PROMPT:</b> ~ts", [FoundPrompt]),
{RetTag,{prompt,FoundPrompt}};
match_line(Line,[{prompt,PromptType}|Patterns],FoundPrompt,EO,RetTag)
when PromptType=/=FoundPrompt ->
@@ -1048,7 +1048,7 @@ match_line(Line,[{Tag,Pattern}|Patterns],FoundPrompt,EO,RetTag) ->
nomatch ->
match_line(Line,Patterns,FoundPrompt,EO,RetTag);
{match,Match} ->
- try_cont_log("<b>MATCH:</b> ~s", [Line]),
+ try_cont_log("<b>MATCH:</b> ~ts", [Line]),
{RetTag,{Tag,Match}}
end;
match_line(Line,[Pattern|Patterns],FoundPrompt,EO,RetTag) ->
@@ -1056,13 +1056,13 @@ match_line(Line,[Pattern|Patterns],FoundPrompt,EO,RetTag) ->
nomatch ->
match_line(Line,Patterns,FoundPrompt,EO,RetTag);
{match,Match} ->
- try_cont_log("<b>MATCH:</b> ~s", [Line]),
+ try_cont_log("<b>MATCH:</b> ~ts", [Line]),
{RetTag,Match}
end;
match_line(Line,[],FoundPrompt,EO,match) ->
match_line(Line,EO#eo.haltpatterns,FoundPrompt,EO,halt);
match_line(Line,[],_FoundPrompt,_EO,halt) ->
- try_cont_log(" ~s", [Line]),
+ try_cont_log(" ~ts", [Line]),
nomatch.
one_line([$\n|Rest],Line) ->
@@ -1086,7 +1086,7 @@ log_lines(String) ->
[] ->
ok;
LastLine ->
- try_cont_log(" ~s", [LastLine])
+ try_cont_log(" ~ts", [LastLine])
end.
log_lines_not_last(String) ->
@@ -1094,7 +1094,7 @@ log_lines_not_last(String) ->
{[],LastLine} ->
LastLine;
{String1,LastLine} ->
- try_cont_log("~s",[String1]),
+ try_cont_log("~ts",[String1]),
LastLine
end.
diff --git a/lib/common_test/src/ct_telnet_client.erl b/lib/common_test/src/ct_telnet_client.erl
index d703b39ac5..7329498ed6 100644
--- a/lib/common_test/src/ct_telnet_client.erl
+++ b/lib/common_test/src/ct_telnet_client.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. 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
@@ -308,7 +308,7 @@ cmd_dbg(_Cmd) ->
[Opt] -> Opt;
_ -> Opts
end,
- io:format("~s(~w): ~w\n", [CtrlStr,Ctrl,Opts1]);
+ io:format("~ts(~w): ~w\n", [CtrlStr,Ctrl,Opts1]);
Any ->
io:format("Unexpected in cmd_dbg:~n~w~n",[Any])
end.
diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl
index 4f3597dffb..e341391a91 100644
--- a/lib/common_test/src/ct_testspec.erl
+++ b/lib/common_test/src/ct_testspec.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. 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
@@ -736,7 +736,7 @@ add_option({Key,Value},Node,List,WarnIfExists) when is_list(Value) ->
NewOption = case lists:keyfind(Key,1,OldOptions) of
{Key,OldOption} when WarnIfExists,OldOption/=[]->
io:format("There is an option ~w=~w already "
- "defined for node ~p, skipping new ~w~n",
+ "defined for node ~w, skipping new ~w~n",
[Key,OldOption,Node,Value]),
OldOption;
{Key,OldOption}->
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index cf891ed043..0f2b2081d9 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2003-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2003-2013. 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
@@ -396,14 +396,14 @@ loop(Mode,TestData,StartDir) ->
%% A connection crashed - remove the connection but don't die
ct_logs:tc_log_async(ct_error_notify,
"Connection process died: "
- "Pid: ~p, Address: ~p, Callback: ~p\n"
+ "Pid: ~w, Address: ~p, Callback: ~w\n"
"Reason: ~p\n\n",
[Pid,A,CB,Reason]),
catch CB:close(Pid),
loop(Mode,TestData,StartDir);
_ ->
%% Let process crash in case of error, this shouldn't happen!
- io:format("\n\nct_util_server got EXIT from ~p: ~p\n\n",
+ io:format("\n\nct_util_server got EXIT from ~w: ~p\n\n",
[Pid,Reason]),
file:set_cwd(StartDir),
exit(Reason)
@@ -956,7 +956,7 @@ open_url(iexplore, Args, URL) ->
Path = proplists:get_value(default, Paths),
[Cmd | _] = string:tokens(Path, "%"),
Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL,
- io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd1]),
+ io:format(user, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd1]),
open_port({spawn,Cmd1}, []);
_ ->
io:format("~nNo path to iexplore.exe~n",[])
@@ -969,6 +969,6 @@ open_url(Prog, Args, URL) ->
is_list(Prog) -> Prog
end,
Cmd = ProgStr ++ " " ++ Args ++ " " ++ URL,
- io:format(user, "~nOpening ~s with command:~n ~s~n", [URL,Cmd]),
+ io:format(user, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd]),
open_port({spawn,Cmd},[]),
ok.
diff --git a/lib/common_test/src/cth_conn_log.erl b/lib/common_test/src/cth_conn_log.erl
index 255f3ec78a..644594e34d 100644
--- a/lib/common_test/src/cth_conn_log.erl
+++ b/lib/common_test/src/cth_conn_log.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2013. 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
@@ -105,8 +105,9 @@ pre_init_per_testcase(TestCase,Config,CthState) ->
"<table borders=1>"
"<b>" ++ ConnModStr ++ " logs:</b>\n" ++
[io_lib:format(
- "<tr><td>~p</td><td><a href=~p>~s</a></td></tr>",
- [S,L,filename:basename(L)])
+ "<tr><td>~p</td><td><a href=\"~ts\">~ts</a>"
+ "</td></tr>",
+ [S,ct_logs:uri(L),filename:basename(L)])
|| {S,L} <- Ls] ++
"</table>",
io:format(Str,[]),
diff --git a/lib/common_test/src/cth_surefire.erl b/lib/common_test/src/cth_surefire.erl
index e6eaad8d48..1a38b6584b 100644
--- a/lib/common_test/src/cth_surefire.erl
+++ b/lib/common_test/src/cth_surefire.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2013. 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
@@ -297,7 +297,7 @@ sanitize([]) ->
now_to_string(Now) ->
{{YY,MM,DD},{HH,Mi,SS}} = calendar:now_to_local_time(Now),
- io_lib:format("~p-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B",[YY,MM,DD,HH,Mi,SS]).
+ io_lib:format("~w-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B",[YY,MM,DD,HH,Mi,SS]).
make_url(undefined,_) ->
undefined;
diff --git a/lib/common_test/src/unix_telnet.erl b/lib/common_test/src/unix_telnet.erl
index 25b9d4d5d2..99ce92e9f1 100644
--- a/lib/common_test/src/unix_telnet.erl
+++ b/lib/common_test/src/unix_telnet.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2004-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2004-2013. 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
@@ -110,7 +110,7 @@ connect1(Ip,Port,Timeout,KeepAlive,Username,Password) ->
case ct_telnet:silent_teln_expect(Pid,[],[prompt],?prx,[]) of
{ok,{prompt,?username},_} ->
ok = ct_telnet_client:send_data(Pid,Username),
- cont_log("Username: ~s",[Username]),
+ cont_log("Username: ~ts",[Username]),
case ct_telnet:silent_teln_expect(Pid,[],prompt,?prx,[]) of
{ok,{prompt,?password},_} ->
ok = ct_telnet_client:send_data(Pid,Password),
diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl
index 6d90b29f41..86ec71c98e 100644
--- a/lib/common_test/test/ct_error_SUITE.erl
+++ b/lib/common_test/test/ct_error_SUITE.erl
@@ -44,8 +44,12 @@
%% there will be clashes with logging processes etc).
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config1 = ct_test_support:init_per_suite(Config),
- Config1.
+ DataDir = ?config(data_dir, Config),
+ TestDir = filename:join(DataDir, "error/test/"),
+ CTH = filename:join(TestDir, "verify_config.erl"),
+ ct:pal("Compiling ~p: ~p",
+ [CTH,compile:file(CTH,[{outdir,TestDir},debug_info])]),
+ ct_test_support:init_per_suite([{path_dirs,[TestDir]} | Config]).
end_per_suite(Config) ->
ct_test_support:end_per_suite(Config).
@@ -61,7 +65,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[cfg_error, lib_error, no_compile, timetrap_end_conf,
timetrap_normal, timetrap_extended, timetrap_parallel,
- timetrap_fun, timetrap_fun_group, misc_errors].
+ timetrap_fun, timetrap_fun_group, misc_errors,
+ config_restored].
groups() ->
[].
@@ -285,6 +290,24 @@ misc_errors(Config) when is_list(Config) ->
TestEvents = events_to_check(misc_errors),
ok = ct_test_support:verify_events(TestEvents, Events, Config).
+%%%-----------------------------------------------------------------
+%%%
+config_restored(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "error/test/config_restored_SUITE"),
+ {Opts,ERPid} = setup([{suite,Suite},
+ {ct_hooks,[verify_config]}],
+ Config),
+ ok = ct_test_support:run(Opts, Config),
+ Events = ct_test_support:get_events(ERPid, Config),
+
+ ct_test_support:log_events(config_restored,
+ reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+
+ TestEvents = events_to_check(config_restored),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
@@ -1439,4 +1462,40 @@ test_events(misc_errors) ->
{?eh,test_stats,{2,7,{0,0}}},
{?eh,test_done,{'DEF','STOP_TIME'}},
{?eh,stop_logging,[]}
+ ];
+
+test_events(config_restored) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,4}},
+ {?eh,tc_start,{config_restored_SUITE,init_per_suite}},
+ {?eh,tc_done,{config_restored_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{config_restored_SUITE,to_tc}},
+ {?eh,cth,{verify_config,post_end_per_testcase,{to_tc,diff_ok}}},
+ {?eh,tc_done,
+ {config_restored_SUITE,to_tc,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,1,{0,0}}},
+ {?eh,tc_start,{config_restored_SUITE,exit_tc}},
+ {?eh,cth,{verify_config,post_end_per_testcase,{exit_tc,diff_ok}}},
+ {?eh,tc_done,{config_restored_SUITE,exit_tc,
+ {failed,{error,{test_case_failed,"Goodbye!"}}}}},
+ {?eh,test_stats,{0,2,{0,0}}},
+ [{?eh,tc_start,{config_restored_SUITE,{init_per_group,g1,[]}}},
+ {?eh,tc_start,{config_restored_SUITE,to_tc}},
+ {?eh,cth,{verify_config,post_end_per_testcase,{to_tc,diff_ok}}},
+ {?eh,tc_done,
+ {config_restored_SUITE,to_tc,{failed,{timetrap_timeout,1000}}}},
+ {?eh,test_stats,{0,3,{0,0}}},
+ {?eh,tc_start,{config_restored_SUITE,exit_tc}},
+ {?eh,cth,{verify_config,post_end_per_testcase,{exit_tc,diff_ok}}},
+ {?eh,tc_done,{config_restored_SUITE,exit_tc,
+ {failed,{error,{test_case_failed,"Goodbye!"}}}}},
+ {?eh,test_stats,{0,4,{0,0}}},
+ {?eh,tc_start,{config_restored_SUITE,{end_per_group,g1,[]}}},
+ {?eh,tc_done,{config_restored_SUITE,{end_per_group,g1,[]},ok}}],
+ {?eh,tc_start,{config_restored_SUITE,end_per_suite}},
+ {?eh,tc_done,{config_restored_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/config_restored_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/config_restored_SUITE.erl
new file mode 100644
index 0000000000..fb47f2bcb9
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/config_restored_SUITE.erl
@@ -0,0 +1,175 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. 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(config_restored_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% Function: suite() -> Info
+%% Info = [tuple()]
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,1000}].
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ Config1 = [{init_per_suite,?MODULE} | Config],
+ TabPid = spawn(fun() ->
+ ets:new(?MODULE, [named_table, set, public]),
+ receive _ -> ok end
+ end),
+ [{tab,TabPid} | Config1].
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config0) -> void() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ ets:delete(?MODULE),
+ exit(?config(tab, Config), kill),
+ 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) ->
+ [{init_per_group,GroupName} | 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(TC, Config) ->
+ Config1 = [{init_per_testcase,TC} | Config],
+ ets:insert(?MODULE, {config,Config}),
+ %% ct:pal("Config after init_per_testcase(~w) = ~p", [TC,Config1]),
+ Config1.
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config0) ->
+%% void() | {save_config,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%%--------------------------------------------------------------------
+end_per_testcase(TC, Config) ->
+ ct:pal("Config in end_per_testcase(~w) = ~p", [TC,Config]),
+ [{_,MemConfig}] = ets:lookup(?MODULE, config),
+ diff_config(Config, MemConfig, [tc_status]),
+ ?MODULE = proplists:get_value(init_per_suite, Config),
+ TC = proplists:get_value(init_per_testcase, Config),
+ case ?config(tc_group_properties, Config) of
+ undefined ->
+ ok;
+ Props ->
+ GName = proplists:get_value(name, Props),
+ GName = proplists:get_value(init_per_group, Config)
+ end,
+ 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,[],[to_tc, exit_tc]}].
+
+%%--------------------------------------------------------------------
+%% Function: all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%%--------------------------------------------------------------------
+all() ->
+ [to_tc, exit_tc,
+ {group,g1}].
+
+
+to_tc(Config) ->
+ %% ct:pal("Config for to_tc = ~p", [Config]),
+ [{_,MemConfig}] = ets:lookup(?MODULE, config),
+ diff_config(Config, MemConfig, []),
+ ct:sleep(2000).
+
+exit_tc(Config) ->
+ %% ct:pal("Config for exit_tc = ~p", [Config]),
+ [{_,MemConfig}] = ets:lookup(?MODULE, config),
+ diff_config(Config, MemConfig, []),
+ ct:fail("Goodbye!").
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+
+diff_config(Cfg1, Cfg2, DiffKeys) ->
+ diff_config(Cfg1, Cfg2, DiffKeys, []).
+
+diff_config([{K,V} | Cfg1], Cfg2, DiffKeys, RemKeys) ->
+ case proplists:get_value(K, Cfg2) of
+ undefined ->
+ diff_config(Cfg1, Cfg2, proplists:delete(K, DiffKeys), RemKeys);
+ V ->
+ diff_config(Cfg1, proplists:delete(K, Cfg2), DiffKeys, RemKeys);
+ _Other ->
+ case proplists:is_defined(K, DiffKeys) of
+ true ->
+ diff_config(Cfg1, Cfg2, proplists:delete(K, DiffKeys), RemKeys);
+ false ->
+ diff_config(Cfg1, Cfg2, DiffKeys, [K | RemKeys])
+ end
+ end;
+diff_config([], [], [], []) ->
+ ct:pal("Diff ok!", []),
+ ok;
+diff_config([], Cfg2, DiffKeys, RemKeys) ->
+ Result = {diff_failed, {cfg2,Cfg2}, {diffkeys,DiffKeys}, {remkeys,RemKeys}},
+ ct:pal("Diff failed! Result = ~p", [Result]),
+ exit(Result).
+
diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl
new file mode 100644
index 0000000000..40a54b9f99
--- /dev/null
+++ b/lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl
@@ -0,0 +1,239 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2012. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%% @doc Common Test Example Suite Callback module.
+%%%
+%%% <p>This module gives an example of a common test CTH (Common Test Hook).
+%%% There are many ways to add a CTH to a test run, you can do it either in
+%%% the command line using -ct_hook, in a test spec using
+%%% {ct_hook,M} or in the suite it self by returning ct_hook
+%%% from either suite/0, init_per_suite/1, init_per_group/2 and
+%%% init_per_testcase/2. The scope of the CTH is determined by where is it
+%%% started. If it is started in the command line or test spec then it will
+%%% be stopped at the end of all tests. If it is started in init_per_suite,
+%%% it will be stopped after end_per_suite and so on. See terminate
+%%% documentation for a table describing the scoping machanics.
+%%%
+%%% All of callbacks except init/1 in a CTH are optional.</p>
+
+-module(verify_config).
+
+%% CT Hooks
+-export([id/1]).
+-export([init/2]).
+
+-export([pre_init_per_suite/3]).
+-export([post_init_per_suite/4]).
+-export([pre_end_per_suite/3]).
+-export([post_end_per_suite/4]).
+
+-export([pre_init_per_group/3]).
+-export([post_init_per_group/4]).
+-export([pre_end_per_group/3]).
+-export([post_end_per_group/4]).
+
+-export([pre_init_per_testcase/3]).
+-export([post_end_per_testcase/4]).
+
+-export([on_tc_fail/3]).
+-export([on_tc_skip/3]).
+
+-export([terminate/1]).
+
+-include_lib("common_test/src/ct_util.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-type config() :: proplists:proplist().
+-type reason() :: term().
+-type skip_or_fail() :: {skip, reason()} |
+ {auto_skip, reason()} |
+ {fail, reason()} |
+ {'EXIT',reason()}.
+
+-record(state, { id = ?MODULE :: term()}).
+
+%% @doc Always called before any other callback function. Use this to initiate
+%% any common state. It should return an state for this CTH.
+-spec init(Id :: term(), Opts :: proplists:proplist()) ->
+ {ok, State :: #state{}}.
+init(Id, Opts) ->
+ {ok,Opts}.
+
+%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's
+%% return the same ID the seconds CTH is ignored. This function should NOT
+%% have any side effects as it might be called multiple times by common test.
+-spec id(Opts :: proplists:proplist()) ->
+ Id :: term().
+id(Opts) ->
+ now().
+
+%% @doc Called before init_per_suite is called. Note that this callback is
+%% only called if the CTH is added before init_per_suite is run (eg. in a test
+%% specification, suite/0 function etc).
+%% You can change the config in the this function.
+-spec pre_init_per_suite(Suite :: atom(),
+ Config :: config(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+pre_init_per_suite(Suite,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after init_per_suite.
+%% you can change the return value in this function.
+-spec post_init_per_suite(Suite :: atom(),
+ Config :: config(),
+ Return :: config() | skip_or_fail(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+post_init_per_suite(Suite,Config,Return,State) ->
+ {Return, State}.
+
+%% @doc Called before end_per_suite. The config/state can be changed here,
+%% though it will only affect the *end_per_suite function.
+-spec pre_end_per_suite(Suite :: atom(),
+ Config :: config() | skip_or_fail(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+pre_end_per_suite(Suite,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after end_per_suite. Note that the config cannot be
+%% changed here, only the status of the suite.
+-spec post_end_per_suite(Suite :: atom(),
+ Config :: config(),
+ Return :: term(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+post_end_per_suite(Suite,Config,Return,State) ->
+ {Return, State}.
+
+%% @doc Called before each init_per_group.
+%% You can change the config in this function.
+-spec pre_init_per_group(Group :: atom(),
+ Config :: config(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+pre_init_per_group(Group,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after each init_per_group.
+%% You can change the return value in this function.
+-spec post_init_per_group(Group :: atom(),
+ Config :: config(),
+ Return :: config() | skip_or_fail(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+post_init_per_group(Group,Config,Return,State) ->
+ {Return, State}.
+
+%% @doc Called after each end_per_group. The config/state can be changed here,
+%% though it will only affect the *end_per_group functions.
+-spec pre_end_per_group(Group :: atom(),
+ Config :: config() | skip_or_fail(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+pre_end_per_group(Group,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after each end_per_group. Note that the config cannot be
+%% changed here, only the status of the group.
+-spec post_end_per_group(Group :: atom(),
+ Config :: config(),
+ Return :: term(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+post_end_per_group(Group,Config,Return,State) ->
+ {Return, State}.
+
+%% @doc Called before each test case.
+%% You can change the config in this function.
+-spec pre_init_per_testcase(TC :: atom(),
+ Config :: config(),
+ State :: #state{}) ->
+ {config() | skip_or_fail(), NewState :: #state{}}.
+pre_init_per_testcase(TC,Config,State) ->
+ {Config, State}.
+
+%% @doc Called after each test case. Note that the config cannot be
+%% changed here, only the status of the test case.
+-spec post_end_per_testcase(TC :: atom(),
+ Config :: config(),
+ Return :: term(),
+ State :: #state{}) ->
+ {ok | skip_or_fail(), NewState :: #state{}}.
+post_end_per_testcase(TC,Config,Return,State) ->
+ %% check that config has been restored
+ ct:pal("Config in verify_config:post_end_per_testcase(~w) = ~p",
+ [TC,Config]),
+ [{_,MemConfig}] = ets:lookup(config_restored_SUITE, config),
+ try config_restored_SUITE:diff_config(Config, MemConfig, [tc_status]) of
+ ok ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_end_per_testcase,
+ {TC,diff_ok}}})
+ catch
+ _:_ ->
+ gen_event:notify(
+ ?CT_EVMGR_REF, #event{ name = cth, node = node(),
+ data = {?MODULE, post_end_per_testcase,
+ {TC,diff_failed}}})
+ end,
+ {Return, State}.
+
+%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
+%% post_end_per_group and post_end_per_tc if the suite, group or test case failed.
+%% This function should be used for extra cleanup which might be needed.
+%% It is not possible to modify the config or the status of the test run.
+-spec on_tc_fail(TC :: init_per_suite | end_per_suite |
+ init_per_group | end_per_group | atom(),
+ Reason :: term(), State :: #state{}) ->
+ NewState :: #state{}.
+on_tc_fail(TC, Reason, State) ->
+ State.
+
+%% @doc Called when a test case is skipped by either user action
+%% or due to an init function failing. Test case can be
+%% end_per_suite, init_per_group, end_per_group and the actual test cases.
+-spec on_tc_skip(TC :: end_per_suite |
+ init_per_group | end_per_group | atom(),
+ {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} |
+ {tc_user_skip, {skipped, Reason :: term()}},
+ State :: #state{}) ->
+ NewState :: #state{}.
+on_tc_skip(TC, Reason, State) ->
+ State.
+
+%% @doc Called when the scope of the CTH is done, this depends on
+%% when the CTH was specified. This translation table describes when this
+%% function is called.
+%%
+%% | Started in | terminate called |
+%% |---------------------|-------------------------|
+%% | command_line | after all tests are run |
+%% | test spec | after all tests are run |
+%% | suite/0 | after SUITE is done |
+%% | init_per_suite/1 | after SUITE is done |
+%% | init_per_group/2 | after group is done |
+%% |-----------------------------------------------|
+%%
+-spec terminate(State :: #state{}) ->
+ term().
+terminate(State) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 405df1e978..796a0832d7 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -64,7 +64,7 @@ end_per_testcase(TestCase, Config) ->
suite() ->
- [{timetrap,{seconds,20}}].
+ [{timetrap,{minutes,1}}].
all() ->
all(suite).
diff --git a/lib/common_test/test/ct_master_SUITE.erl b/lib/common_test/test/ct_master_SUITE.erl
index 64d34a0c9b..0f336d2d79 100644
--- a/lib/common_test/test/ct_master_SUITE.erl
+++ b/lib/common_test/test/ct_master_SUITE.erl
@@ -154,6 +154,9 @@ make_spec(DataDir, FileName, NodeNames, Suites, Config) ->
{init,NodeName,[
{node_start,[{startup_functions,[]},
{monitor_master,true},
+ {boot_timeout,10},
+ {init_timeout,10},
+ {startup_timeout,10},
{env,Env}]},
{eval,{erlang,nodes,[]}}]
}
diff --git a/lib/common_test/test/ct_master_SUITE_data/master/master_SUITE.erl b/lib/common_test/test/ct_master_SUITE_data/master/master_SUITE.erl
index 8a5009ad62..df54c4419c 100644
--- a/lib/common_test/test/ct_master_SUITE_data/master/master_SUITE.erl
+++ b/lib/common_test/test/ct_master_SUITE_data/master/master_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2013. 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
diff --git a/lib/common_test/test/ct_netconfc_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE.erl
index 3042a924fe..c89a4cdabe 100644
--- a/lib/common_test/test/ct_netconfc_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE.erl
@@ -43,12 +43,11 @@
%% there will be clashes with logging processes etc).
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config1 = ct_test_support:init_per_suite(Config),
case application:load(crypto) of
- {error,Reason} ->
+ {error,Reason} when Reason=/={already_loaded,crypto} ->
{skip, Reason};
_ ->
- Config1
+ ct_test_support:init_per_suite(Config)
end.
end_per_suite(Config) ->
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
index d337158bce..54526e8e83 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -1044,12 +1044,9 @@ gen_dsa(LSize,NSize) when is_integer(LSize), is_integer(NSize) ->
Key = gen_dsa2(LSize, NSize),
{Key, encode_key(Key)}.
-encode_key(Key = #'RSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('RSAPrivateKey', Key),
- {'RSAPrivateKey', list_to_binary(Der), not_encrypted};
encode_key(Key = #'DSAPrivateKey'{}) ->
- {ok, Der} = 'OTP-PUB-KEY':encode('DSAPrivateKey', Key),
- {'DSAPrivateKey', list_to_binary(Der), not_encrypted}.
+ Der = public_key:der_encode('DSAPrivateKey', Key),
+ {'DSAPrivateKey', Der, not_encrypted}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
index 2427f37f52..09217f60a3 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2013. 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
@@ -426,7 +426,7 @@ reply(ConnRef,Reply) ->
send(ConnRef, make_msg(Reply)).
from_simple(Simple) ->
- list_to_binary(xmerl:export_simple_element(Simple,xmerl_xml)).
+ unicode_c2b(xmerl:export_simple_element(Simple,xmerl_xml)).
xml(Content) ->
<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
@@ -435,30 +435,30 @@ xml(Content) ->
rpc_reply(Content) when is_binary(Content) ->
MsgId = case erase(msg_id) of
undefined -> <<>>;
- Id -> list_to_binary([" message-id=\"",Id,"\""])
+ Id -> unicode_c2b([" message-id=\"",Id,"\""])
end,
<<"<rpc-reply xmlns=\"",?NETCONF_NAMESPACE,"\"",MsgId/binary,">\n",
Content/binary,"\n</rpc-reply>">>;
rpc_reply(Content) ->
- rpc_reply(list_to_binary(Content)).
+ rpc_reply(unicode_c2b(Content)).
session_id(no_session_id) ->
<<>>;
session_id(SessionId0) ->
- SessionId = list_to_binary(integer_to_list(SessionId0)),
+ SessionId = unicode_c2b(integer_to_list(SessionId0)),
<<"<session-id>",SessionId/binary,"</session-id>\n">>.
capabilities(undefined) ->
- CapsXml = list_to_binary([["<capability>",C,"</capability>\n"]
+ CapsXml = unicode_c2b([["<capability>",C,"</capability>\n"]
|| C <- ?CAPABILITIES]),
<<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>;
capabilities({base,Vsn}) ->
- CapsXml = list_to_binary([["<capability>",C,"</capability>\n"]
+ CapsXml = unicode_c2b([["<capability>",C,"</capability>\n"]
|| C <- ?CAPABILITIES_VSN(Vsn)]),
<<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>;
capabilities(no_base) ->
[_|Caps] = ?CAPABILITIES,
- CapsXml = list_to_binary([["<capability>",C,"</capability>\n"] || C <- Caps]),
+ CapsXml = unicode_c2b([["<capability>",C,"</capability>\n"] || C <- Caps]),
<<"<capabilities>\n",CapsXml/binary,"</capabilities>\n">>;
capabilities(no_caps) ->
<<>>.
@@ -553,3 +553,8 @@ make_msg(Xml) when is_binary(Xml) ->
xml(Xml);
make_msg(Simple) when is_tuple(Simple) ->
xml(from_simple(Simple)).
+
+%%%-----------------------------------------------------------------
+%%% Convert to unicode binary, since we use UTF-8 encoding in XML
+unicode_c2b(Characters) ->
+ unicode:characters_to_binary(Characters).
diff --git a/lib/common_test/test/ct_surefire_SUITE.erl b/lib/common_test/test/ct_surefire_SUITE.erl
index 69e98cef48..b86b47f0a2 100644
--- a/lib/common_test/test/ct_surefire_SUITE.erl
+++ b/lib/common_test/test/ct_surefire_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2013. 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
@@ -32,6 +32,7 @@
-include_lib("common_test/include/ct_event.hrl").
-include_lib("xmerl/include/xmerl.hrl").
+-include_lib("kernel/include/file.hrl").
-define(eh, ct_test_support_eh).
@@ -77,53 +78,52 @@ all() ->
%%%-----------------------------------------------------------------
%%%
default(Config) when is_list(Config) ->
- run(default,[cth_surefire],Config),
- PrivDir = ?config(priv_dir,Config),
- XmlRe = filename:join([PrivDir,"*","junit_report.xml"]),
- check_xml(default,XmlRe).
+ run(default,[cth_surefire],"junit_report.xml",Config).
absolute_path(Config) when is_list(Config) ->
PrivDir = ?config(priv_dir,Config),
Path = filename:join(PrivDir,"abspath.xml"),
- run(absolute_path,[{cth_surefire,[{path,Path}]}],Config),
- check_xml(absolute_path,Path).
+ run(absolute_path,[{cth_surefire,[{path,Path}]}],Path,Config).
relative_path(Config) when is_list(Config) ->
Path = "relpath.xml",
- run(relative_path,[{cth_surefire,[{path,Path}]}],Config),
- PrivDir = ?config(priv_dir,Config),
- XmlRe = filename:join([PrivDir,"*",Path]),
- check_xml(relative_path,XmlRe).
+ run(relative_path,[{cth_surefire,[{path,Path}]}],Path,Config).
url(Config) when is_list(Config) ->
Path = "url.xml",
- run(url,[{cth_surefire,[{url_base,?url_base},
- {path,Path}]}],Config),
- PrivDir = ?config(priv_dir,Config),
- XmlRe = filename:join([PrivDir,"*",Path]),
- check_xml(url,XmlRe).
+ run(url,[{cth_surefire,[{url_base,?url_base},{path,Path}]}],
+ Path,Config).
logdir(Config) when is_list(Config) ->
- PrivDir = ?config(priv_dir,Config),
- LogDir = filename:join(PrivDir,"specific_logdir"),
- file:make_dir(LogDir),
+ Opts = ct_test_support:get_opts(Config),
+ LogDir =
+ case lists:keyfind(logdir,1,Opts) of
+ {logdir,LD} -> LD;
+ false -> ?config(priv_dir,Config)
+ end,
+ MyLogDir = filename:join(LogDir,"specific_logdir"),
+ ensure_exists_empty(MyLogDir),
Path = "logdir.xml",
- run(logdir,[{cth_surefire,[{path,Path}]}],Config,[{logdir,LogDir}]),
- PrivDir = ?config(priv_dir,Config),
- XmlRe = filename:join([LogDir,"*",Path]),
- check_xml(logdir,XmlRe).
+ run(logdir,[{cth_surefire,[{path,Path}]}],Path,Config,[{logdir,MyLogDir}]).
%%%-----------------------------------------------------------------
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
-run(Case,CTHs,Config) ->
- run(Case,CTHs,Config,[]).
-run(Case,CTHs,Config,ExtraOpts) ->
+run(Case,CTHs,Report,Config) ->
+ run(Case,CTHs,Report,Config,[]).
+run(Case,CTHs,Report,Config,ExtraOpts) ->
DataDir = ?config(data_dir, Config),
Suite = filename:join(DataDir, "surefire_SUITE"),
{Opts,ERPid} = setup([{suite,Suite},{ct_hooks,CTHs},{label,Case}|ExtraOpts],
Config),
- ok = execute(Case, Opts, ERPid, Config).
+ ok = execute(Case, Opts, ERPid, Config),
+ LogDir =
+ case lists:keyfind(logdir,1,Opts) of
+ {logdir,LD} -> LD;
+ false -> ?config(priv_dir,Config)
+ end,
+ Re = filename:join([LogDir,"*",Report]),
+ check_xml(Case,Re).
setup(Test, Config) ->
Opts0 = ct_test_support:get_opts(Config),
@@ -349,3 +349,26 @@ get_numbers_from_attrs([_|A],T,E,F,S) ->
get_numbers_from_attrs(A,T,E,F,S);
get_numbers_from_attrs([],T,E,F,S) ->
{T,E,F,S}.
+
+ensure_exists_empty(Dir) ->
+ case file:list_dir(Dir) of
+ {error,enoent} ->
+ file:make_dir(Dir);
+ {ok,Files} ->
+ del_files(Dir,Files)
+ end.
+
+del_files(Dir,[F0|Fs] ) ->
+ F = filename:join(Dir,F0),
+ case file:read_file_info(F) of
+ {ok,#file_info{type=directory}} ->
+ {ok,Files} = file:list_dir(F),
+ del_files(F,Files),
+ file:del_dir(F),
+ del_files(Dir,Fs);
+ _ ->
+ file:delete(F),
+ del_files(Dir,Fs)
+ end;
+del_files(_,[]) ->
+ ok.
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 1319fa4154..7c33fd404d 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2013. 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
@@ -1043,8 +1043,8 @@ result_match({SkipOrFail,{ErrorInd,{EMod,EFunc,{Why,'_'}}}},
true;
result_match({failed,{timetrap_timeout,{'$approx',Num}}},
{failed,{timetrap_timeout,Value}}) ->
- if Value >= trunc(Num-0.02*Num),
- Value =< trunc(Num+0.02*Num) -> true;
+ if Value >= trunc(Num-0.05*Num),
+ Value =< trunc(Num+0.05*Num) -> true;
true -> false
end;
result_match({user_timetrap_error,{Why,'_'}},
diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk
index f9bb22867e..c92fb2ca37 100644
--- a/lib/common_test/vsn.mk
+++ b/lib/common_test/vsn.mk
@@ -1 +1 @@
-COMMON_TEST_VSN = 1.6.3
+COMMON_TEST_VSN = 1.7