aboutsummaryrefslogtreecommitdiffstats
path: root/lib/common_test/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common_test/test')
-rw-r--r--lib/common_test/test/Makefile7
-rw-r--r--lib/common_test/test/ct_auto_clean_SUITE.erl262
-rw-r--r--lib/common_test/test/ct_auto_clean_SUITE_data/ac_SUITE.erl181
-rw-r--r--lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl214
-rw-r--r--lib/common_test/test/ct_config_SUITE.erl14
-rw-r--r--lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_error_SUITE_data/error/test/verify_config.erl38
-rw-r--r--lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl8
-rw-r--r--lib/common_test/test/ct_hooks_SUITE.erl25
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl22
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl42
-rw-r--r--lib/common_test/test/ct_keep_logs_SUITE.erl199
-rw-r--r--lib/common_test/test/ct_keep_logs_SUITE_data/keep_logs_SUITE.erl32
-rw-r--r--lib/common_test/test/ct_log_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE.erl7
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl79
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl4
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/ns.erl11
-rw-r--r--lib/common_test/test/ct_pre_post_test_io_SUITE.erl10
-rw-r--r--lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl10
-rw-r--r--lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl10
-rw-r--r--lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_surefire_SUITE.erl8
-rw-r--r--lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_test_support.erl140
-rw-r--r--lib/common_test/test/ct_test_support_eh.erl8
-rw-r--r--lib/common_test/test/ct_testspec_1_SUITE.erl8
-rw-r--r--lib/common_test/test/ct_unicode_SUITE.erl218
-rw-r--r--lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl98
-rw-r--r--lib/common_test/test/ct_userconfig_callback.erl4
-rw-r--r--lib/common_test/test/ct_verbosity_SUITE.erl6
-rw-r--r--lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl8
-rw-r--r--lib/common_test/test/erl2html2_SUITE.erl10
-rw-r--r--lib/common_test/test/telnet_server.erl20
-rw-r--r--lib/common_test/test/test_server_SUITE.erl15
-rw-r--r--lib/common_test/test/test_server_test_lib.erl8
38 files changed, 1499 insertions, 259 deletions
diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile
index 2f0fc2e05a..ecd1f727a2 100644
--- a/lib/common_test/test/Makefile
+++ b/lib/common_test/test/Makefile
@@ -1,7 +1,7 @@
#
# %CopyrightBegin%
#
-# Copyright Ericsson AB 2008-2016. All Rights Reserved.
+# Copyright Ericsson AB 2008-2017. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -71,7 +71,10 @@ MODULES= \
test_server_test_lib \
ct_release_test_SUITE \
ct_log_SUITE \
- ct_SUITE
+ ct_SUITE \
+ ct_keep_logs_SUITE \
+ ct_unicode_SUITE \
+ ct_auto_clean_SUITE
ERL_FILES= $(MODULES:%=%.erl)
HRL_FILES= test_server_test_lib.hrl
diff --git a/lib/common_test/test/ct_auto_clean_SUITE.erl b/lib/common_test/test/ct_auto_clean_SUITE.erl
new file mode 100644
index 0000000000..a89c90eb79
--- /dev/null
+++ b/lib/common_test/test/ct_auto_clean_SUITE.erl
@@ -0,0 +1,262 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ct_auto_clean_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_suite(Config0) -> Config1 | {skip,Reason}
+%%
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the suite.
+%%
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ DataDir = ?config(data_dir, Config),
+ CTHs = filelib:wildcard(filename:join(DataDir,"cth_*.erl")),
+ ct:pal("CTHs: ~p",[CTHs]),
+ [ct:pal("Compiling ~p: ~p",
+ [FileName,compile:file(FileName,[{outdir,DataDir},debug_info])]) ||
+ FileName <- CTHs],
+ ct_test_support:init_per_suite([{path_dirs,[DataDir]} | Config]).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_suite(Config) -> void()
+%%
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after the suite.
+%%--------------------------------------------------------------------
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+%%--------------------------------------------------------------------
+%% Function: init_per_testcase(TestCase, Config0) -> Config1 |
+%% {skip,Reason}
+%% TestCase = atom()
+%% Name of the test case that is about to run.
+%% Config0 = Config1 = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Initialization before each test case.
+%%
+%% Note: This function is free to add any key/value pairs to the Config
+%% variable, but should NOT alter/remove any existing entries.
+%%--------------------------------------------------------------------
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+%%--------------------------------------------------------------------
+%% Function: end_per_testcase(TestCase, Config) -> void()
+%%
+%% TestCase = atom()
+%% Name of the test case that is finished.
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%%
+%% Description: Cleanup after each test case.
+%%--------------------------------------------------------------------
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+%%--------------------------------------------------------------------
+%% Function: all(Clause) -> Descr | TestCases | {skip,Reason}
+%%
+%% Clause = doc | suite
+%% Indicates expected return value.
+%% Descr = [string()] | []
+%% String that describes the test suite.
+%% TestCases = [TestCase]
+%% TestCase = atom()
+%% Name of a test case.
+%% Reason = term()
+%% The reason for skipping the test suite.
+%%
+%% Description: Returns a description of the test suite (doc) and a
+%% list of all test cases in the suite (suite).
+%%--------------------------------------------------------------------
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [clean].
+
+groups() ->
+ [].
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Function: TestCase(Arg) -> Descr | Spec | ok | exit() | {skip,Reason}
+%%
+%% Arg = doc | suite | Config
+%% Indicates expected behaviour and return value.
+%% Config = [tuple()]
+%% A list of key/value pairs, holding the test case configuration.
+%% Descr = [string()] | []
+%% String that describes the test case.
+%% Spec = [tuple()] | []
+%% A test specification.
+%% Reason = term()
+%% The reason for skipping the test case.
+%%
+%% Description: Test case function. Returns a description of the test
+%% case (doc), then returns a test specification (suite),
+%% or performs the actual test (Config).
+%%--------------------------------------------------------------------
+
+%%%-----------------------------------------------------------------
+%%%
+
+clean(Config) when is_list(Config) ->
+ DataDir = ?config(data_dir, Config),
+
+ ACSuite = filename:join(DataDir, "ac_SUITE"),
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = eh_opts(Config) ++ Opts0 ++ [{suite,ACSuite},
+ {ct_hooks,[cth_auto_clean]}],
+
+ ERPid = ct_test_support:start_event_receiver(Config),
+
+ ok = ct_test_support:run(Opts, Config),
+
+ Events = ct_test_support:get_events(ERPid, Config),
+ ct_test_support:log_events(?FUNCTION_NAME,
+ ct_test_support:reformat(Events, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+ TestEvents = events_to_check(?FUNCTION_NAME),
+ ok = ct_test_support:verify_events(TestEvents, Events, Config).
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+eh_opts(Config) ->
+ Level = ?config(trace_level, Config),
+ [{event_handler,{?eh,[{cbm,ct_test_support},{trace_level,Level}]}}].
+
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ events(Test) ++ events_to_check(Test, N-1).
+
+events(clean) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,9}},
+
+ {?eh,tc_start,{ac_SUITE,init_per_suite}},
+ {?eh,tc_done,{ac_SUITE,init_per_suite,ok}},
+
+ {?eh,tc_start,{ac_SUITE,tc1}},
+ {?eh,tc_done,{ac_SUITE,tc1,ok}},
+
+ {?eh,test_stats,{1,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,tc2}},
+ {?eh,tc_done,{ac_SUITE,tc2,ok}},
+
+ {?eh,test_stats,{2,0,{0,0}}},
+
+ [{?eh,tc_start,{ac_SUITE,{init_per_group,s1,[]}}},
+ {?eh,tc_done,{ac_SUITE,{init_per_group,s1,[]},ok}},
+
+ {?eh,tc_start,{ac_SUITE,stc1}},
+ {?eh,tc_done,{ac_SUITE,stc1,ok}},
+
+ {?eh,test_stats,{3,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,stc2}},
+ {?eh,tc_done,{ac_SUITE,stc2,ok}},
+
+ {?eh,test_stats,{4,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,{end_per_group,s1,[]}}},
+ {?eh,tc_done,{ac_SUITE,{end_per_group,s1,[]},ok}}],
+
+ {parallel,
+ [{?eh,tc_start,{ac_SUITE,{init_per_group,p1,[parallel]}}},
+ {?eh,tc_done,{ac_SUITE,{init_per_group,p1,[parallel]},ok}},
+
+ {?eh,tc_start,{ac_SUITE,ptc1}},
+ {?eh,tc_start,{ac_SUITE,ptc2}},
+ {?eh,tc_done,{ac_SUITE,ptc1,ok}},
+ {?eh,test_stats,{5,0,{0,0}}},
+ {?eh,tc_done,{ac_SUITE,ptc2,ok}},
+ {?eh,test_stats,{6,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,{end_per_group,p1,[parallel]}}},
+ {?eh,tc_done,{ac_SUITE,{end_per_group,p1,[parallel]},ok}}]},
+
+ [{?eh,tc_start,{ac_SUITE,{init_per_group,s2,[]}}},
+ {?eh,tc_done,{ac_SUITE,{init_per_group,s2,[]},ok}},
+
+ {?eh,tc_start,{ac_SUITE,stc1}},
+ {?eh,tc_done,{ac_SUITE,stc1,ok}},
+
+ {?eh,test_stats,{7,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,stc2}},
+ {?eh,tc_done,{ac_SUITE,stc2,ok}},
+
+ {?eh,test_stats,{8,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,{end_per_group,s2,[]}}},
+ {?eh,tc_done,{ac_SUITE,{end_per_group,s2,[]},ok}}],
+
+ {?eh,tc_start,{ac_SUITE,tc1}},
+ {?eh,tc_done,{ac_SUITE,tc1,ok}},
+
+ {?eh,test_stats,{9,0,{0,0}}},
+
+ {?eh,tc_start,{ac_SUITE,end_per_suite}},
+ {?eh,tc_done,{ac_SUITE,end_per_suite,ok}},
+
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
diff --git a/lib/common_test/test/ct_auto_clean_SUITE_data/ac_SUITE.erl b/lib/common_test/test/ct_auto_clean_SUITE_data/ac_SUITE.erl
new file mode 100644
index 0000000000..e779f70693
--- /dev/null
+++ b/lib/common_test/test/ct_auto_clean_SUITE_data/ac_SUITE.erl
@@ -0,0 +1,181 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ac_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+%%--------------------------------------------------------------------
+%% @spec suite() -> Info
+%% Info = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+%%--------------------------------------------------------------------
+%% @spec init_per_suite(Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ start_processes(),
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_suite(Config0) -> term() | {save_config,Config1}
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_suite(_Config) ->
+ start_processes(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_group(GroupName, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_group(_GroupName, Config) ->
+ start_processes(),
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_group(GroupName, Config0) ->
+%% term() | {save_config,Config1}
+%% GroupName = atom()
+%% Config0 = Config1 = [tuple()]
+%% @end
+%%--------------------------------------------------------------------
+end_per_group(_GroupName, _Config) ->
+ start_processes(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec init_per_testcase(TestCase, Config0) ->
+%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+init_per_testcase(_TestCase, Config) ->
+ start_processes(),
+ Config.
+
+%%--------------------------------------------------------------------
+%% @spec end_per_testcase(TestCase, Config0) ->
+%% term() | {save_config,Config1} | {fail,Reason}
+%% TestCase = atom()
+%% Config0 = Config1 = [tuple()]
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+end_per_testcase(_TestCase, _Config) ->
+ start_processes(),
+ ok.
+
+%%--------------------------------------------------------------------
+%% @spec 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
+%% @end
+%%--------------------------------------------------------------------
+groups() ->
+ [{s1,[],[stc1,stc2]},
+ {p1,[parallel],[ptc1,ptc2]},
+ {s2,[],[stc1,stc2]}].
+
+%%! What about nested groups??
+
+%%--------------------------------------------------------------------
+%% @spec all() -> GroupsAndTestCases | {skip,Reason}
+%% GroupsAndTestCases = [{group,GroupName} | TestCase]
+%% GroupName = atom()
+%% TestCase = atom()
+%% Reason = term()
+%% @end
+%%--------------------------------------------------------------------
+all() ->
+ [
+ [tc1,tc2],
+ {group,s1},
+ {group,p1},
+ {group,s2},
+ tc1
+ ].
+
+tc1(_Config) ->
+ start_processes(),
+ ok.
+
+tc2(_Config) ->
+ start_processes(),
+ ok.
+
+stc1(_Config) ->
+ start_processes(),
+ ok.
+
+stc2(_Config) ->
+ start_processes(),
+ ok.
+
+ptc1(_Config) ->
+ start_processes(),
+ ok.
+
+ptc2(_Config) ->
+ start_processes(),
+ ok.
+
+
+%%%-----------------------------------------------------------------
+%%%
+
+start_processes() ->
+ Init = fun() ->
+ process_flag(trap_exit, true),
+ do_spawn(fun() -> receive _ -> ok end end),
+ receive _ ->
+ ok
+ end
+ end,
+ do_spawn(Init).
+
+do_spawn(Fun) ->
+ Pid = spawn(Fun),
+ ct:log("Process ~w started with group leader ~w",
+ [Pid,element(2, process_info(Pid, group_leader))]),
+ Pid.
diff --git a/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl b/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl
new file mode 100644
index 0000000000..3f8d3957cc
--- /dev/null
+++ b/lib/common_test/test/ct_auto_clean_SUITE_data/cth_auto_clean.erl
@@ -0,0 +1,214 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(cth_auto_clean).
+
+%% CTH Callbacks
+-export([id/1, init/2,
+ pre_init_per_suite/3, post_init_per_suite/4,
+ pre_end_per_suite/3, post_end_per_suite/4,
+ pre_init_per_group/4, post_init_per_group/5,
+ pre_end_per_group/4, post_end_per_group/5,
+ pre_init_per_testcase/4, post_init_per_testcase/5,
+ pre_end_per_testcase/4, post_end_per_testcase/5]).
+
+id(_Opts) ->
+ ?MODULE.
+
+init(?MODULE, _Opts) ->
+ ok.
+
+pre_init_per_suite(_Suite, Config, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = test_server_io:get_gl(true),
+ SharedGL = find_and_kill(),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ %% get status of processes at startup, to be compared with end result
+ {Config, [{all_procs,processes()} | State]}.
+
+post_init_per_suite(_Suite, _Config, Return, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Return, State}.
+
+pre_end_per_suite(_Suite, Config, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Config, State}.
+
+post_end_per_suite(_Suite, _Config, Return, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ AllProcs = processes(),
+ Remaining = AllProcs--proplists:get_value(all_procs, State),
+ ct:pal("Final remaining processes = ~p", [Remaining]),
+ %% only the end_per_suite process shoud remain at this point!
+ Remaining = [self()],
+ {Return, State}.
+
+pre_init_per_group(_Suite, _Group, Config, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(procs_and_gls),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Config, State}.
+
+post_init_per_group(_Suite, _Group, _Config, Result, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(procs_and_gls),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Result, State}.
+
+pre_init_per_testcase(_Suite, _TC, Config, State) ->
+ identify(?FUNCTION_NAME),
+ ThisGL = group_leader(),
+ find_and_kill(proc, ThisGL),
+ case proplists:get_value(tc_group_properties, Config) of
+ [{name,_},parallel] ->
+ timer:sleep(1000);
+ _ ->
+ do_until(fun() -> element(1,ct:remaining_test_procs()) end, [])
+ end,
+ {Config, State}.
+
+post_init_per_testcase(_Suite, _TC, Config, Return, State) ->
+ identify(?FUNCTION_NAME),
+ ThisGL = group_leader(),
+ find_and_kill(proc, ThisGL),
+ case proplists:get_value(tc_group_properties, Config) of
+ [{name,_},parallel] ->
+ timer:sleep(1000);
+ _ ->
+ do_until(fun() -> element(1,ct:remaining_test_procs()) end, [])
+ end,
+ {Return, State}.
+
+pre_end_per_testcase(_Suite, _TC, Config, State) ->
+ identify(?FUNCTION_NAME),
+ ThisGL = group_leader(),
+ find_and_kill(proc, ThisGL),
+ case proplists:get_value(tc_group_properties, Config) of
+ [{name,_},parallel] ->
+ timer:sleep(1000);
+ _ ->
+ do_until(fun() -> element(1,ct:remaining_test_procs()) end, [])
+ end,
+ {Config, State}.
+
+post_end_per_testcase(_Suite, _TC, Config, Result, State) ->
+ identify(?FUNCTION_NAME),
+ ThisGL = group_leader(),
+ find_and_kill(proc, ThisGL),
+ case proplists:get_value(tc_group_properties, Config) of
+ [{name,_},parallel] ->
+ timer:sleep(1000);
+ _ ->
+ do_until(fun() -> element(1,ct:remaining_test_procs()) end, [])
+ end,
+ {Result, State}.
+
+pre_end_per_group(_Suite, _Group, Config, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(procs_and_gls),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Config, State}.
+
+post_end_per_group(_Suite, _Group, _Config, Return, State) ->
+ identify(?FUNCTION_NAME),
+ SharedGL = find_and_kill(procs_and_gls),
+ do_until(fun() -> ct:remaining_test_procs() end, {[],SharedGL,[]}),
+ {Return, State}.
+
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+
+identify(Func) ->
+ ct:pal("********** THIS IS ~w on ~w", [Func, self()]),
+ ok.
+
+find_and_kill() ->
+ find_and_kill(procs).
+
+find_and_kill(procs) ->
+ {Procs,SharedGL,_ParallelGLs} = ct:remaining_test_procs(),
+ ct:pal("Remaining test processes = ~p", [pi(Procs)]),
+ [pkill(P, kill) || {P,_GL} <- Procs],
+ SharedGL;
+
+find_and_kill(procs_and_gls) ->
+ {Procs,SharedGL,GLs} = ct:remaining_test_procs(),
+ ct:pal("Remaining test processes = ~p", [pi(Procs)]),
+ [pkill(P, kill) || {P,_GL} <- Procs],
+ ct:pal("Remaining group leaders = ~p", [pi(GLs)]),
+ [pkill(GL, kill) || GL <- GLs, GL /= SharedGL],
+ SharedGL.
+
+find_and_kill(proc, ProcGL) ->
+ {Procs,SharedGL,GLs} = ct:remaining_test_procs(),
+ ct:pal("Remaining test processes = ~p", [pi(Procs++GLs)]),
+ [pkill(P, kill) || {P,GL} <- Procs, GL == ProcGL],
+ SharedGL.
+
+pi([{P,_GL}|Ps]) ->
+ pi([P|Ps]);
+pi([P|Ps]) ->
+ case node() == node(P) of
+ true ->
+ {_,GL} = process_info(P,group_leader),
+ {_,CF} = process_info(P,current_function),
+ {_,IC} = process_info(P,initial_call),
+ {_,D} = process_info(P,dictionary),
+ Shared = test_server_io:get_gl(true),
+ User = whereis(user),
+ if (GL /= P) and (GL /= Shared) and (GL /= User) ->
+ [{P,GL,CF,IC,D} | pi([GL|Ps])];
+ true ->
+ [{P,GL,CF,IC,D} | pi(Ps)]
+ end;
+ false ->
+ pi(Ps)
+ end;
+pi([]) ->
+ [].
+
+do_until(Fun, Until) ->
+ io:format("Will do until ~p~n", [Until]),
+ do_until(Fun, Until, 1000).
+
+do_until(_, Until, 0) ->
+ io:format("Couldn't get ~p~n", [Until]),
+ exit({not_reached,Until});
+
+do_until(Fun, Until, N) ->
+ case Fun() of
+ Until ->
+ ok;
+ _Tmp ->
+ do_until(Fun, Until, N-1)
+ end.
+
+pkill(P, How) ->
+ ct:pal("KILLING ~w NOW!", [P]),
+ exit(P, How).
+
diff --git a/lib/common_test/test/ct_config_SUITE.erl b/lib/common_test/test/ct_config_SUITE.erl
index cbbfe408a8..5ffc735d6a 100644
--- a/lib/common_test/test/ct_config_SUITE.erl
+++ b/lib/common_test/test/ct_config_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -172,10 +172,10 @@ testspec_dynamic(Config) when is_list(Config) ->
%%% HELP FUNCTIONS
%%%-----------------------------------------------------------------
make_spec(DataDir, ConfigDir, Filename, Suites, Config)->
- {ok, Fd} = file:open(filename:join(ConfigDir, Filename), [write]),
- ok = file:write(Fd,
- io_lib:format("{suites, \"~sconfig/test/\", ~p}.~n", [DataDir, Suites])),
- lists:foreach(fun(C)-> ok=file:write(Fd, io_lib:format("~p.~n", [C])) end, Config),
+ {ok, Fd} = file:open(filename:join(ConfigDir, Filename),
+ [write, {encoding,utf8}]),
+ ok = io:format(Fd,"{suites, \"~tsconfig/test/\", ~p}.~n", [DataDir, Suites]),
+ lists:foreach(fun(C)-> ok=io:format(Fd, "~tp.~n", [C]) end, Config),
ok = file:close(Fd).
run_test(Name, Config, CTConfig, SuiteNames)->
@@ -213,8 +213,8 @@ reformat_events(Events, EH) ->
skip_dynamic() ->
case os:getenv("TS_EXTRA_PLATFORM_LABEL") of
TSExtraPlatformLabel when is_list(TSExtraPlatformLabel) ->
- case string:str(TSExtraPlatformLabel,"TimeWarpingOS") of
- 0 -> false;
+ case string:find(TSExtraPlatformLabel,"TimeWarpingOS") of
+ nomatch -> false;
_ -> true
end;
_ ->
diff --git a/lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl b/lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl
index 4e013b8056..e9e8b2a54d 100644
--- a/lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl
+++ b/lib/common_test/test/ct_cover_SUITE_data/cover_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,9 +23,7 @@
%% Description:
%% This file contains the test cases for the code coverage support
%%
-%% @author Support
-%% @doc Test of code coverage support in common_test
-%% @end
+%% Test of code coverage support in common_test
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(cover_SUITE).
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
index 530ee09654..ef8c05cb2e 100644
--- 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
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Example Suite Callback module.
+%%% Common Test Example Suite Callback module.
%%%
-%%% <p>This module gives an example of a common test CTH (Common Test Hook).
+%%% 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
@@ -31,7 +31,7 @@
%%% 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>
+%%% All of callbacks except init/1 in a CTH are optional.
-module(verify_config).
@@ -69,14 +69,14 @@
-record(state, { id = ?MODULE :: term()}).
-%% @doc Always called before any other callback function. Use this to initiate
+%% 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
+%% 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()) ->
@@ -84,7 +84,7 @@ init(Id, Opts) ->
id(Opts) ->
os:timestamp().
-%% @doc Called before init_per_suite is called. Note that this callback is
+%% 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.
@@ -95,7 +95,7 @@ id(Opts) ->
pre_init_per_suite(Suite,Config,State) ->
{Config, State}.
-%% @doc Called after init_per_suite.
+%% Called after init_per_suite.
%% you can change the return value in this function.
-spec post_init_per_suite(Suite :: atom(),
Config :: config(),
@@ -105,7 +105,7 @@ pre_init_per_suite(Suite,Config,State) ->
post_init_per_suite(Suite,Config,Return,State) ->
{Return, State}.
-%% @doc Called before end_per_suite. The config/state can be changed here,
+%% 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(),
@@ -114,7 +114,7 @@ post_init_per_suite(Suite,Config,Return,State) ->
pre_end_per_suite(Suite,Config,State) ->
{Config, State}.
-%% @doc Called after end_per_suite. Note that the config cannot be
+%% 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(),
@@ -124,7 +124,7 @@ pre_end_per_suite(Suite,Config,State) ->
post_end_per_suite(Suite,Config,Return,State) ->
{Return, State}.
-%% @doc Called before each init_per_group.
+%% Called before each init_per_group.
%% You can change the config in this function.
-spec pre_init_per_group(Group :: atom(),
Config :: config(),
@@ -133,7 +133,7 @@ post_end_per_suite(Suite,Config,Return,State) ->
pre_init_per_group(Group,Config,State) ->
{Config, State}.
-%% @doc Called after each init_per_group.
+%% Called after each init_per_group.
%% You can change the return value in this function.
-spec post_init_per_group(Group :: atom(),
Config :: config(),
@@ -143,7 +143,7 @@ pre_init_per_group(Group,Config,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,
+%% 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(),
@@ -152,7 +152,7 @@ post_init_per_group(Group,Config,Return,State) ->
pre_end_per_group(Group,Config,State) ->
{Config, State}.
-%% @doc Called after each end_per_group. Note that the config cannot be
+%% 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(),
@@ -162,7 +162,7 @@ pre_end_per_group(Group,Config,State) ->
post_end_per_group(Group,Config,Return,State) ->
{Return, State}.
-%% @doc Called before each test case.
+%% Called before each test case.
%% You can change the config in this function.
-spec pre_init_per_testcase(TC :: atom(),
Config :: config(),
@@ -171,7 +171,7 @@ post_end_per_group(Group,Config,Return,State) ->
pre_init_per_testcase(TC,Config,State) ->
{Config, State}.
-%% @doc Called after each test case. Note that the config cannot be
+%% 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(),
@@ -198,7 +198,7 @@ post_end_per_testcase(TC,Config,Return,State) ->
end,
{Return, State}.
-%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
+%% 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.
@@ -209,7 +209,7 @@ post_end_per_testcase(TC,Config,Return,State) ->
on_tc_fail(TC, Reason, State) ->
State.
-%% @doc Called when a test case is skipped by either user action
+%% 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 |
@@ -221,7 +221,7 @@ on_tc_fail(TC, Reason, State) ->
on_tc_skip(TC, Reason, State) ->
State.
-%% @doc Called when the scope of the CTH is done, this depends on
+%% 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.
%%
diff --git a/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl b/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
index 07b21b4178..e4c7be3cac 100644
--- a/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
+++ b/lib/common_test/test/ct_event_handler_SUITE_data/eh_A.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
%% %CopyrightEnd%
%%
-%%% @doc Event handler module
+%%% Event handler module
%%%
-%%% <p>This is an event handler module used for testing that
-%%% Common Test generates events as expected.</p>
+%%% This is an event handler module used for testing that
+%%% Common Test generates events as expected.
%%%
-module(eh_A).
diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl
index 8ba14e63bc..0f5636a789 100644
--- a/lib/common_test/test/ct_hooks_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -257,16 +257,21 @@ cth_log(Config) when is_list(Config) ->
lists:foreach(
fun(UnexpIoLog) ->
{ok,Bin} = file:read_file(UnexpIoLog),
- Ts = string:tokens(binary_to_list(Bin),[$\n]),
- Matches = lists:foldl(fun([$=,$E,$R,$R,$O,$R|_], N) ->
- N+1;
- ([$L,$o,$g,$g,$e,$r|_], N) ->
- N+1;
+ Ts = string:lexemes(binary_to_list(Bin),[$\n]),
+ Matches = lists:foldl(fun([$=,$E,$R,$R,$O,$R|_], {E,I,L}) ->
+ {E+1,I,L};
+ ([$=,$I,$N,$F,$O|_], {E,I,L}) ->
+ {E,I+1,L};
+ ([$L,$o,$g,$g,$e,$r|_], {E,I,L}) ->
+ {E,I,L+1};
(_, N) -> N
- end, 0, Ts),
- ct:pal("~p matches in ~tp", [Matches,UnexpIoLog]),
- if Matches > 10 -> ok;
- true -> exit({no_unexpected_io_found,UnexpIoLog})
+ end, {0,0,0}, Ts),
+ ct:pal("~p ({Error,Info,Log}) matches in ~tp",
+ [Matches,UnexpIoLog]),
+ MatchList = tuple_to_list(Matches),
+ case [N || N <- MatchList, N<3] of
+ [] -> ok;
+ _ -> exit({missing_unexpected_io,UnexpIoLog})
end
end, UnexpIoLogs),
ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl
index d400348354..404fb33476 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_scope_per_tc_cth_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -29,7 +29,6 @@
%% Test server callback functions
%%--------------------------------------------------------------------
-%% @doc
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%%
@@ -38,27 +37,23 @@
%% Note: This function is free to add any key/value pairs to the Config
%% variable, but should NOT alter/remove any existing entries.
%%
-%% @spec init_per_suite(Config) -> Config
-%% @end
+%% -spec init_per_suite(Config) -> Config
%%--------------------------------------------------------------------
init_per_suite(Config) ->
Config.
%%--------------------------------------------------------------------
-%% @doc
%% Config - [tuple()]
%% A list of key/value pairs, holding the test case configuration.
%%
%% Cleanup after the whole suite
%%
-%% @spec end_per_suite(Config) -> _
-%% @end
+%% -spec end_per_suite(Config) -> _
%%--------------------------------------------------------------------
end_per_suite(_Config) ->
ok.
%%--------------------------------------------------------------------
-%% @doc
%% Case - atom()
%% Name of the test case that is about to be run.
%% Config - [tuple()]
@@ -70,14 +65,12 @@ end_per_suite(_Config) ->
%% variable, but should NOT alter/remove any existing entries.
%% Initiation before each test case
%%
-%% @spec init_per_testcase(TestCase, Config) -> Config
-%% @end
+%% -spec init_per_testcase(TestCase, Config) -> Config
%%--------------------------------------------------------------------
init_per_testcase(_TestCase, Config) ->
[{ct_hooks,[empty_cth]}|Config].
%%--------------------------------------------------------------------
-%% @doc
%% Case - atom()
%% Name of the test case that is about to be run.
%% Config - [tuple()]
@@ -85,22 +78,19 @@ init_per_testcase(_TestCase, Config) ->
%%
%% Cleanup after each test case
%%
-%% @spec end_per_testcase(TestCase, Config) -> _
-%% @end
+%% -spec end_per_testcase(TestCase, Config) -> _
%%--------------------------------------------------------------------
end_per_testcase(_TestCase, _Config) ->
ok.
%%--------------------------------------------------------------------
-%% @doc
%% TestCases - [Case]
%% Case - atom()
%% Name of a test case.
%%
%% Returns a list of all test cases in this test suite
%%
-%% @spec all() -> TestCases
-%% @end
+%% -spec all() -> TestCases
%%--------------------------------------------------------------------
all() ->
[test_case].
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl
index bd1ac54781..eda190b682 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/cth_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -124,6 +124,6 @@ gen() ->
gen_loop(N) ->
ct:log("Logger iteration: ~p", [N]),
error_logger:error_report(N),
- error_logger:info_report(progress, N),
+ error_logger:info_report(N),
ct:sleep(150),
gen_loop(N+1).
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
index 961ea68d2d..c648367838 100644
--- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
+++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Example Suite Callback module.
+%%% Common Test Example Suite Callback module.
%%%
-%%% <p>This module gives an example of a common test CTH (Common Test Hook).
+%%% 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
@@ -31,7 +31,7 @@
%%% 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>
+%%% All of callbacks except init/1 in a CTH are optional.
-module(empty_cth).
@@ -71,7 +71,7 @@
-record(state, { id = ?MODULE :: term()}).
-%% @doc Always called before any other callback function. Use this to initiate
+%% 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{}}.
@@ -81,7 +81,7 @@ init(Id, Opts) ->
ct:log("~w:init called", [?MODULE]),
{ok,Opts}.
-%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's
+%% 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()) ->
@@ -92,7 +92,7 @@ id(Opts) ->
ct:log("~w:id called", [?MODULE]),
ct_test_support:unique_timestamp().
-%% @doc Called before init_per_suite is called. Note that this callback is
+%% 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.
@@ -108,7 +108,7 @@ pre_init_per_suite(Suite,Config,State) ->
ct:log("~w:pre_init_per_suite(~w) called", [?MODULE,Suite]),
{Config, State}.
-%% @doc Called after init_per_suite.
+%% Called after init_per_suite.
%% you can change the return value in this function.
-spec post_init_per_suite(Suite :: atom(),
Config :: config(),
@@ -123,7 +123,7 @@ post_init_per_suite(Suite,Config,Return,State) ->
ct:log("~w:post_init_per_suite(~w) called", [?MODULE,Suite]),
{Return, State}.
-%% @doc Called before end_per_suite. The config/state can be changed here,
+%% 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(),
@@ -137,7 +137,7 @@ pre_end_per_suite(Suite,Config,State) ->
ct:log("~w:pre_end_per_suite(~w) called", [?MODULE,Suite]),
{Config, State}.
-%% @doc Called after end_per_suite. Note that the config cannot be
+%% 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(),
@@ -152,7 +152,7 @@ post_end_per_suite(Suite,Config,Return,State) ->
ct:log("~w:post_end_per_suite(~w) called", [?MODULE,Suite]),
{Return, State}.
-%% @doc Called before each init_per_group.
+%% Called before each init_per_group.
%% You can change the config in this function.
-spec pre_init_per_group(Suite :: atom(),
Group :: atom(),
@@ -167,7 +167,7 @@ pre_init_per_group(Suite,Group,Config,State) ->
ct:log("~w:pre_init_per_group(~w,~w) called", [?MODULE,Suite,Group]),
{Config, State}.
-%% @doc Called after each init_per_group.
+%% Called after each init_per_group.
%% You can change the return value in this function.
-spec post_init_per_group(Suite :: atom(),
Group :: atom(),
@@ -183,7 +183,7 @@ post_init_per_group(Suite,Group,Config,Return,State) ->
ct:log("~w:post_init_per_group(~w,~w) called", [?MODULE,Suite,Group]),
{Return, State}.
-%% @doc Called after each end_per_group. The config/state can be changed here,
+%% 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(Suite :: atom(),
Group :: atom(),
@@ -198,7 +198,7 @@ pre_end_per_group(Suite,Group,Config,State) ->
ct:log("~w:pre_end_per_group(~w~w) called", [?MODULE,Suite,Group]),
{Config, State}.
-%% @doc Called after each end_per_group. Note that the config cannot be
+%% 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(Suite :: atom(),
Group :: atom(),
@@ -214,7 +214,7 @@ post_end_per_group(Suite,Group,Config,Return,State) ->
ct:log("~w:post_end_per_group(~w,~w) called", [?MODULE,Suite,Group]),
{Return, State}.
-%% @doc Called before init_per_testcase/2 for each test case.
+%% Called before init_per_testcase/2 for each test case.
%% You can change the config in this function.
-spec pre_init_per_testcase(Suite :: atom(),
TC :: atom(),
@@ -229,7 +229,7 @@ pre_init_per_testcase(Suite,TC,Config,State) ->
ct:log("~w:pre_init_per_testcase(~w,~w) called", [?MODULE,Suite,TC]),
{Config, State}.
-%% @doc Called after init_per_testcase/2, and before the test case.
+%% Called after init_per_testcase/2, and before the test case.
-spec post_init_per_testcase(Suite :: atom(),
TC :: atom(),
Config :: config(),
@@ -244,7 +244,7 @@ post_init_per_testcase(Suite,TC,Config,Return,State) ->
ct:log("~w:post_init_per_testcase(~w,~w) called", [?MODULE,Suite,TC]),
{Return, State}.
-%% @doc Called before end_per_testacse/2. No skip or fail allowed here,
+%% Called before end_per_testacse/2. No skip or fail allowed here,
%% only config additions.
-spec pre_end_per_testcase(Suite :: atom(),
TC :: atom(),
@@ -259,7 +259,7 @@ pre_end_per_testcase(Suite,TC,Config,State) ->
ct:log("~w:pre_end_per_testcase(~w,~w) called", [?MODULE,Suite,TC]),
{Config, State}.
-%% @doc Called after end_per_testcase/2 for each test case. Note that
+%% Called after end_per_testcase/2 for each test case. Note that
%% the config cannot be changed here, only the status of the test case.
-spec post_end_per_testcase(Suite :: atom(),
TC :: atom(),
@@ -275,7 +275,7 @@ post_end_per_testcase(Suite,TC,Config,Return,State) ->
ct:log("~w:post_end_per_testcase(~w,~w) called", [?MODULE,Suite,TC]),
{Return, State}.
-%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
+%% 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.
@@ -292,7 +292,7 @@ on_tc_fail(Suite, TC, Reason, State) ->
ct:log("~w:on_tc_fail(~w,~w) called", [?MODULE,Suite,TC]),
State.
-%% @doc Called when a test case is skipped by either user action
+%% 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(Suite :: atom(),
@@ -310,7 +310,7 @@ on_tc_skip(Suite, TC, Reason, State) ->
ct:log("~w:on_tc_skip(~w,~w) called", [?MODULE,Suite,TC]),
State.
-%% @doc Called when the scope of the CTH is done, this depends on
+%% 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.
%%
diff --git a/lib/common_test/test/ct_keep_logs_SUITE.erl b/lib/common_test/test/ct_keep_logs_SUITE.erl
new file mode 100644
index 0000000000..83b7963d7d
--- /dev/null
+++ b/lib/common_test/test/ct_keep_logs_SUITE.erl
@@ -0,0 +1,199 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_keep_logs_SUITE
+%%%
+%%% Description:
+%%% Test the 'keep_logs' option
+%%%
+%%%-------------------------------------------------------------------
+-module(ct_keep_logs_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+init_per_suite(Config0) ->
+ ct_test_support:init_per_suite(Config0).
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [
+ keep_logs,
+ refresh_logs
+ ].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+
+%% Test the keep_logs option with normal common_test runs
+keep_logs(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "keep_logs_SUITE"),
+ Opts0 = ct_test_support:get_opts(Config),
+ Opts = [{suite,Suite},{label,keep_logs} | Opts0],
+
+ LogDir=?config(logdir,Opts),
+ KeepLogsDir = create_dir(filename:join(LogDir,"keep_logs-")),
+ Opts1 = lists:keyreplace(logdir,1,Opts,{logdir,KeepLogsDir}),
+ ct:log("New LogDir = ~ts", [KeepLogsDir]),
+
+ %% Create 6 ct_run.* log directories
+ [ok = ct_test_support:run(Opts1, Config) || _ <- lists:seq(1,3)],
+
+ %% Verify the number of directories
+ WC = filename:join(KeepLogsDir,"ct_run.ct@*"),
+ L1 = filelib:wildcard(WC),
+ 6 = length(L1),
+
+ %% Keep all logs
+ {1,0,{0,0}}=ct_test_support:run_ct_run_test([{keep_logs,all}|Opts1], Config),
+ L2 = filelib:wildcard(WC),
+ 7 = length(L2),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,all}|Opts1], Config),
+ L3 = filelib:wildcard(WC),
+ 8 = length(L3),
+
+ %% N<length of list
+ {1,0,{0,0}}=ct_test_support:run_ct_run_test([{keep_logs,7}|Opts1], Config),
+ L4 = filelib:wildcard(WC),
+ 7 = length(L4),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,6}|Opts1], Config),
+ L5 = filelib:wildcard(WC),
+ 6 = length(L5),
+
+ %% N>length of list
+ {1,0,{0,0}}=ct_test_support:run_ct_run_test([{keep_logs,10}|Opts1], Config),
+ L6 = filelib:wildcard(WC),
+ 7 = length(L6),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,10}|Opts1], Config),
+ L7 = filelib:wildcard(WC),
+ 8 = length(L7),
+
+ %% N==length of list
+ {1,0,{0,0}}=ct_test_support:run_ct_run_test([{keep_logs,8}|Opts1], Config),
+ L8 = filelib:wildcard(WC),
+ 8 = length(L8),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,8}|Opts1], Config),
+ L9 = filelib:wildcard(WC),
+ 8 = length(L9),
+
+ %% N==length of list + current run
+ {1,0,{0,0}}=ct_test_support:run_ct_run_test([{keep_logs,9}|Opts1], Config),
+ L10 = filelib:wildcard(WC),
+ 9 = length(L10),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,10}|Opts1], Config),
+ L11 = filelib:wildcard(WC),
+ 10 = length(L11),
+
+ {ok,Content} = file:list_dir(KeepLogsDir),
+ ct:log("Deleting dir: ~p~nContent: ~p~n",[KeepLogsDir,Content]),
+ ct_test_support:rm_dir(KeepLogsDir).
+
+%% Test the keep_logs option togwther with the refresh_logs option
+refresh_logs(Config) ->
+ DataDir = ?config(data_dir, Config),
+ Suite = filename:join(DataDir, "keep_logs_SUITE"),
+ Opts0 = ct_test_support:get_opts(Config),
+ LogDir=?config(logdir,Opts0),
+ KeepLogsDir = create_dir(filename:join(LogDir,"refresh_logs-")),
+ Opts1 = lists:keyreplace(logdir,1,Opts0,{logdir,KeepLogsDir}),
+ ct:log("New LogDir = ~ts", [KeepLogsDir]),
+
+ %% Create 6 ct_run.* log directories
+ SuiteOpts = [{suite,Suite},{label,refresh_logs} | Opts1],
+ [ok = ct_test_support:run(SuiteOpts, Config) || _ <- lists:seq(1,3)],
+
+ %% Verify the number of directories
+ WC = filename:join(KeepLogsDir,"ct_run.ct@*"),
+ L1 = filelib:wildcard(WC),
+ 6 = length(L1),
+
+ RefreshOpts = [{refresh_logs,KeepLogsDir},{label,refresh_logs} | Opts1],
+
+ %% Keep all logs (note that refresh_logs option prevents the
+ %% creation of a new log directory for the current run)
+ done = ct_test_support:run_ct_run_test([{keep_logs,all}|RefreshOpts], Config),
+ L2 = filelib:wildcard(WC),
+ 6 = length(L2),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,all}|RefreshOpts],Config),
+ L3 = filelib:wildcard(WC),
+ 6 = length(L3),
+
+ %% N<length of list
+ done = ct_test_support:run_ct_run_test([{keep_logs,5}|RefreshOpts], Config),
+ L5 = filelib:wildcard(WC),
+ 5 = length(L5),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,4}|RefreshOpts], Config),
+ L6 = filelib:wildcard(WC),
+ 4 = length(L6),
+
+ %% N>length of list
+ done = ct_test_support:run_ct_run_test([{keep_logs,5}|RefreshOpts], Config),
+ L7 = filelib:wildcard(WC),
+ 4 = length(L7),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,5}|RefreshOpts], Config),
+ L8 = filelib:wildcard(WC),
+ 4 = length(L8),
+
+ %% N==length of list
+ done = ct_test_support:run_ct_run_test([{keep_logs,4}|RefreshOpts], Config),
+ L9 = filelib:wildcard(WC),
+ 4 = length(L9),
+ 0 = ct_test_support:run_ct_script_start([{keep_logs,4}|RefreshOpts], Config),
+ L10 = filelib:wildcard(WC),
+ 4 = length(L10),
+
+ {ok,Content} = file:list_dir(KeepLogsDir),
+ ct:log("Deleting dir: ~p~nContent: ~p~n",[KeepLogsDir,Content]),
+ ct_test_support:rm_dir(KeepLogsDir).
+
+%%%-----------------------------------------------------------------
+%%% Internal
+create_dir(Prefix) ->
+ I = erlang:unique_integer([positive]),
+ Dir = Prefix ++ integer_to_list(I),
+ case filelib:is_dir(Dir) of
+ true ->
+ %% Try again
+ create_dir(Prefix);
+ false ->
+ ok = file:make_dir(Dir),
+ Dir
+ end.
diff --git a/lib/common_test/test/ct_keep_logs_SUITE_data/keep_logs_SUITE.erl b/lib/common_test/test/ct_keep_logs_SUITE_data/keep_logs_SUITE.erl
new file mode 100644
index 0000000000..c78080748b
--- /dev/null
+++ b/lib/common_test/test/ct_keep_logs_SUITE_data/keep_logs_SUITE.erl
@@ -0,0 +1,32 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+-module(keep_logs_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+suite() ->
+ [].
+all() ->
+ [test_case].
+
+test_case(_Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_log_SUITE.erl b/lib/common_test/test/ct_log_SUITE.erl
index 93affda398..214eb17e1a 100644
--- a/lib/common_test/test/ct_log_SUITE.erl
+++ b/lib/common_test/test/ct_log_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -174,7 +174,7 @@ verify(Config) ->
TcLogFile = proplists:get_value(the_logfile, SavedCfg),
Pid = proplists:get_value(the_pid, SavedCfg),
StrPid = lists:flatten(io_lib:format("~p",[Pid])),
- EscPid = "&lt;" ++ string:substr(StrPid, 2, length(StrPid)-2) ++ "&gt;",
+ EscPid = "&lt;" ++ string:slice(StrPid, 1, length(StrPid)-2) ++ "&gt;",
String = proplists:get_value(the_string, SavedCfg),
ct:log("Read from prev testcase: ~p & ~p", [TcLogFile,Pid]),
{ok,Dev} = file:open(TcLogFile, [read]),
diff --git a/lib/common_test/test/ct_netconfc_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE.erl
index 8932f930d1..e8c7b65140 100644
--- a/lib/common_test/test/ct_netconfc_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -52,9 +52,8 @@ init_per_suite(Config) ->
end.
check_crypto_and_ssh() ->
- (catch code:load_file(crypto)),
- case code:is_loaded(crypto) of
- {file,_} ->
+ case code:ensure_loaded(crypto) of
+ {module,_} ->
case catch ssh:start() of
Ok when Ok==ok; Ok=={error,{already_started,ssh}} ->
ct:log("ssh started",[]),
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 2aa6c4d354..a2fa099a8c 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
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,9 +23,7 @@
%% Description:
%% This file contains the test cases for the ct_netconfc API.
%%
-%% @author Support
-%% @doc Netconf Client Interface.
-%% @end
+%% Netconf Client Interface.
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(netconfc1_SUITE).
@@ -102,7 +100,9 @@ all() ->
receive_one_event,
receive_multiple_events,
receive_event_and_rpc,
- receive_event_and_rpc_in_chunks
+ receive_event_and_rpc_in_chunks,
+ multiple_channels,
+ kill_session_same_connection
]
end.
@@ -124,7 +124,7 @@ end_per_testcase(_Case, _Config) ->
ok.
init_per_suite(Config) ->
- (catch code:load_file(crypto)),
+ code:ensure_loaded(crypto),
case {ssh:start(),code:is_loaded(crypto)} of
{Ok,{file,_}} when Ok==ok; Ok=={error,{already_started,ssh}} ->
ct:log("ssh started",[]),
@@ -498,10 +498,11 @@ kill_session(Config) ->
?NS:hello(2),
?NS:expect(2,hello),
- {ok,_OtherClient} = open(SshDir),
+ {ok,OtherClient} = open(SshDir),
?NS:expect_do_reply('kill-session',{kill,2},ok),
?ok = ct_netconfc:kill_session(Client,2),
+ {error,_}=ct_netconfc:get(OtherClient,{server,[{xmlns,"myns"}],[]}),
?NS:expect_do_reply('close-session',close,ok),
?ok = ct_netconfc:close_session(Client),
@@ -1179,13 +1180,73 @@ receive_event_and_rpc_in_chunks(Config) ->
?ok = ct_netconfc:close_session(Client),
ok.
+multiple_channels(Config) ->
+ SshDir = ?config(ssh_dir,Config),
+ SshOpts = ?DEFAULT_SSH_OPTS(SshDir),
+ {ok,Conn} = ct_netconfc:connect(SshOpts),
+ ?NS:hello(1),
+ ?NS:expect(hello),
+ {ok,Client1} = ct_netconfc:session(Conn),
+ ?NS:hello(2),
+ ?NS:expect(2,hello),
+ {ok,Client2} = ct_netconfc:session(Conn),
+ ?NS:hello(3),
+ ?NS:expect(3,hello),
+ {ok,Client3} = ct_netconfc:session(Conn),
+
+ Data = [{server,[{xmlns,"myns"}],[{name,[],["myserver"]}]}],
+ ?NS:expect_reply(1,'get',{data,Data}),
+ {ok,Data} = ct_netconfc:get(Client1,{server,[{xmlns,"myns"}],[]}),
+ ?NS:expect_reply(2,'get',{data,Data}),
+ {ok,Data} = ct_netconfc:get(Client2,{server,[{xmlns,"myns"}],[]}),
+ ?NS:expect_reply(3,'get',{data,Data}),
+ {ok,Data} = ct_netconfc:get(Client3,{server,[{xmlns,"myns"}],[]}),
+
+ ?NS:expect_do_reply(2,'close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client2),
+
+ ?NS:expect_reply(1,'get',{data,Data}),
+ {ok,Data} = ct_netconfc:get(Client1,{server,[{xmlns,"myns"}],[]}),
+ {error,no_such_client}=ct_netconfc:get(Client2,{server,[{xmlns,"myns"}],[]}),
+ ?NS:expect_reply(3,'get',{data,Data}),
+ {ok,Data} = ct_netconfc:get(Client3,{server,[{xmlns,"myns"}],[]}),
+
+ ?NS:expect_do_reply(1,'close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client1),
+ ?NS:expect_do_reply(3,'close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client3),
+
+ ?ok = ct_netconfc:disconnect(Conn),
+ ok.
+
+kill_session_same_connection(Config) ->
+ SshDir = ?config(ssh_dir,Config),
+ SshOpts = ?DEFAULT_SSH_OPTS(SshDir),
+ {ok,Conn} = ct_netconfc:connect(SshOpts),
+ ?NS:hello(1),
+ ?NS:expect(hello),
+ {ok,Client1} = ct_netconfc:session(Conn),
+ ?NS:hello(2),
+ ?NS:expect(2,hello),
+ {ok,Client2} = ct_netconfc:session(Conn),
+
+ ?NS:expect_do_reply('kill-session',{kill,2},ok),
+ ?ok = ct_netconfc:kill_session(Client1,2),
+ timer:sleep(1000),
+ {error,no_such_client}=ct_netconfc:get(Client2,{server,[{xmlns,"myns"}],[]}),
+
+ ?NS:expect_do_reply('close-session',close,ok),
+ ?ok = ct_netconfc:close_session(Client1),
+
+ ok.
+
%%%-----------------------------------------------------------------
break(_Config) ->
- test_server:break("break test case").
+ ct:break("break test case").
br() ->
- test_server:break("").
+ ct:break("").
%%%-----------------------------------------------------------------
%% Open a netconf session which is not specified in a config file
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
index f2580ad8e9..cbdb4cf11a 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2014-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2014-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ stop_node(Case) ->
init_per_suite(Config) ->
- (catch code:load_file(crypto)),
+ code:ensure_loaded(crypto),
case {ssh:start(),code:is_loaded(crypto)} of
{Ok,{file,_}} when Ok==ok; Ok=={error,{already_started,ssh}} ->
ct:log("SSH started locally",[]),
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 2412ea6aba..656fdb4a40 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-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -231,8 +231,7 @@ data_for_channel(CM, Ch, Data, State) ->
{ok, NewState}
end
catch
- Class:Reason ->
- Stacktrace = erlang:get_stacktrace(),
+ Class:Reason:Stacktrace ->
error_logger:error_report([{?MODULE, data_for_channel},
{request, Data},
{buffer, State#session.buffer},
@@ -254,7 +253,7 @@ data(Data, State = #session{connection = ConnRef,
end.
stop_channel(CM, Ch, State) ->
- ssh:close(CM),
+ ssh_connection:close(CM,Ch),
{stop, Ch, State}.
@@ -290,8 +289,8 @@ send_frag({CM,Ch},Data) ->
%%% Kill ssh connection
-kill({CM,_Ch}) ->
- ssh:close(CM).
+kill({CM,Ch}) ->
+ ssh_connection:close(CM,Ch).
add_expect(SessionId,Add) ->
table_trans(fun do_add_expect/2,[SessionId,Add]).
diff --git a/lib/common_test/test/ct_pre_post_test_io_SUITE.erl b/lib/common_test/test/ct_pre_post_test_io_SUITE.erl
index 7ffe6f045b..bca2d5f3de 100644
--- a/lib/common_test/test/ct_pre_post_test_io_SUITE.erl
+++ b/lib/common_test/test/ct_pre_post_test_io_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -164,7 +164,7 @@ pre_post_io(Config) ->
fun(PrePostIoFile) ->
ct:log("Reading Pre/Post Test IO Log file: ~ts", [PrePostIoFile]),
{ok,Bin} = file:read_file(PrePostIoFile),
- Ts = string:tokens(binary_to_list(Bin),[$\n]),
+ Ts = string:lexemes(binary_to_list(Bin),[$\n]),
PrePostIOEntries =
lists:foldl(fun([$L,$o,$g,$g,$e,$r|_],
{pre,PreLogN,PreErrN,0,0}) ->
@@ -203,7 +203,7 @@ pre_post_io(Config) ->
fun(UnexpIoFile) ->
ct:log("Reading Unexpected IO Log file: ~ts", [UnexpIoFile]),
{ok,Bin} = file:read_file(UnexpIoFile),
- Ts = string:tokens(binary_to_list(Bin),[$\n]),
+ Ts = string:lexemes(binary_to_list(Bin),[$\n]),
UnexpIOEntries =
lists:foldl(fun([$L,$o,$g,$g,$e,$r|_], [LogN,ErrN]) ->
[LogN+1,ErrN];
@@ -241,7 +241,7 @@ try_loop(_Fun, 0) ->
gave_up;
try_loop(Fun, N) ->
try Fun() of
- {error,_} ->
+ {Error,_} when Error==error; Error==badrpc ->
timer:sleep(10),
try_loop(Fun, N-1);
Result ->
@@ -257,7 +257,7 @@ try_loop(M, F, _A, 0) ->
gave_up;
try_loop(M, F, A, N) ->
try apply(M, F, A) of
- {error,_} ->
+ {Error,_Reason} when Error==error; Error==badrpc ->
timer:sleep(10),
try_loop(M, F, A, N-1);
Result ->
diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl
index 1b171801a3..0e10ec187d 100644
--- a/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl
+++ b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -126,12 +126,12 @@ default(Config) ->
auto_per_tc(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
- ["log_private",_] = string:tokens(filename:basename(PrivDir), "."),
+ ["log_private",_] = string:lexemes(filename:basename(PrivDir), "."),
{ok,_} = file:list_dir(PrivDir).
manual_per_tc(Config) ->
PrivDir = proplists:get_value(priv_dir, Config),
- ["log_private",_] = string:tokens(filename:basename(PrivDir), "."),
+ ["log_private",_] = string:lexemes(filename:basename(PrivDir), "."),
{error,_} = file:list_dir(PrivDir),
ok = ct:make_priv_dir(),
{ok,_} = file:list_dir(PrivDir).
diff --git a/lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl b/lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl
index 4ce375b4ee..1a305b1516 100644
--- a/lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl
+++ b/lib/common_test/test/ct_repeat_testrun_SUITE_data/a_test/r1_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,14 +19,6 @@
%%
%%----------------------------------------------------------------------
%% File: r1_SUITE.erl
-%%
-%% Description:
-%%
-%%
-%% @author Support
-%% @doc
-%% @end
-%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(r1_SUITE).
-include_lib("common_test/include/ct.hrl").
diff --git a/lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl b/lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl
index 77bb544080..393cbcc780 100644
--- a/lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl
+++ b/lib/common_test/test/ct_repeat_testrun_SUITE_data/b_test/r2_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -19,14 +19,6 @@
%%
%%----------------------------------------------------------------------
%% File: r2_SUITE.erl
-%%
-%% Description:
-%%
-%%
-%% @author Support
-%% @doc
-%% @end
-%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(r2_SUITE).
-include_lib("common_test/include/ct.hrl").
diff --git a/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl b/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl
index a6533641d8..1c81bbe95d 100644
--- a/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl
+++ b/lib/common_test/test/ct_snmp_SUITE_data/snmp_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,9 +23,7 @@
%% Description:
%% This file contains the test cases for the ct_snmp API.
%%
-%% @author Support
-%% @doc Test of SNMP support in common_test
-%% @end
+%% Test of SNMP support in common_test
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(snmp_SUITE).
diff --git a/lib/common_test/test/ct_surefire_SUITE.erl b/lib/common_test/test/ct_surefire_SUITE.erl
index 832e105517..a71288fb12 100644
--- a/lib/common_test/test/ct_surefire_SUITE.erl
+++ b/lib/common_test/test/ct_surefire_SUITE.erl
@@ -304,7 +304,7 @@ test_events(Test) ->
check_xml(Case,XmlRe) ->
case filelib:wildcard(XmlRe) of
[] ->
- ct:fail("No xml files found with regexp ~p~n", [XmlRe]);
+ ct:fail("No xml files found with regexp ~tp~n", [XmlRe]);
[_] = Xmls when Case==absolute_path ->
do_check_xml(Case,Xmls);
[_,_] = Xmls ->
@@ -326,12 +326,12 @@ check_xml(Case,XmlRe) ->
%% ...
%% </testsuites>
do_check_xml(Case,[Xml|Xmls]) ->
- ct:log("Checking <a href=~p>~s</a>~n",[Xml,Xml]),
+ ct:log("Checking <a href=~tp>~ts</a>~n",[Xml,Xml]),
{E,_} = xmerl_scan:file(Xml),
Expected = events_to_result(lists:flatten(test_events(Case))),
ParseResult = testsuites(Case,E),
- ct:log("Expecting: ~p~n",[Expected]),
- ct:log("Actual : ~p~n",[ParseResult]),
+ ct:log("Expecting: ~tp~n",[Expected]),
+ ct:log("Actual : ~tp~n",[ParseResult]),
Expected = ParseResult,
do_check_xml(Case,Xmls);
do_check_xml(_,[]) ->
diff --git a/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl b/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
index ed10356cdd..7a73e45b43 100644
--- a/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
+++ b/lib/common_test/test/ct_surefire_SUITE_data/surefire_SUITE.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -23,9 +23,7 @@
%% Description:
%% This file contains the test cases for cth_surefire.
%%
-%% @author Support
-%% @doc Test of surefire support in common_test
-%% @end
+%% Test of surefire support in common_test
%%----------------------------------------------------------------------
%%----------------------------------------------------------------------
-module(surefire_SUITE).
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index de4eb00686..388d5d46c6 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-2017. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,9 +18,9 @@
%% %CopyrightEnd%
%%
-%%% @doc Test support functions
+%%% Test support functions
%%%
-%%% <p>This is a support module for testing the Common Test Framework.</p>
+%%% This is a support module for testing the Common Test Framework.
%%%
-module(ct_test_support).
@@ -45,6 +45,8 @@
-export([unique_timestamp/0]).
+-export([rm_dir/1]).
+
-include_lib("kernel/include/file.hrl").
%%%-----------------------------------------------------------------
@@ -65,7 +67,7 @@ init_per_suite(Config, Level) ->
end,
case delete_old_logs(os:type(), Config) of
{'EXIT',DelLogsReason} ->
- test_server:format(0, "Failed to delete old log directories: ~p~n",
+ test_server:format(0, "Failed to delete old log directories: ~tp~n",
[DelLogsReason]);
_ ->
ok
@@ -86,10 +88,11 @@ start_slave(Config, Level) ->
start_slave(ct, Config, Level).
start_slave(NodeName, Config, Level) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
test_server:format(0, "Trying to start ~s~n",
[atom_to_list(NodeName)++"@"++Host]),
- case slave:start(Host, NodeName, []) of
+ PR = proplists:get_value(printable_range,Config,io:printable_range()),
+ case slave:start(Host, NodeName, "+pc " ++ atom_to_list(PR)) of
{error,Reason} ->
test_server:fail(Reason);
{ok,CTNode} ->
@@ -117,7 +120,7 @@ start_slave(NodeName, Config, Level) ->
[true = rpc:call(CTNode, code, add_patha, [D]) || D <- PathDirs],
test_server:format(Level, "Dirs added to code path (on ~w):~n",
[CTNode]),
- [io:format("~s~n", [D]) || D <- PathDirs],
+ [io:format("~ts~n", [D]) || D <- PathDirs],
case proplists:get_value(start_sasl, Config) of
true ->
@@ -159,12 +162,12 @@ init_per_testcase(_TestCase, Config) ->
case lists:keysearch(master, 1, Config) of
false->
test_server:format("See Common Test logs here:\n\n"
- "<a href=\"file://~s/all_runs.html\">~s/all_runs.html</a>\n"
- "<a href=\"file://~s/index.html\">~s/index.html</a>",
+ "<a href=\"file://~ts/all_runs.html\">~ts/all_runs.html</a>\n"
+ "<a href=\"file://~ts/index.html\">~ts/index.html</a>",
[LogDir,LogDir,LogDir,LogDir]);
{value, _}->
test_server:format("See CT Master Test logs here:\n\n"
- "<a href=\"file://~s/master_runs.html\">~s/master_runs.html</a>",
+ "<a href=\"file://~ts/master_runs.html\">~ts/master_runs.html</a>",
[LogDir,LogDir])
end,
Config.
@@ -190,11 +193,11 @@ write_testspec(TestSpec, Dir, Name) ->
write_testspec(TestSpec, filename:join(Dir, Name)).
write_testspec(TestSpec, TSFile) ->
- {ok,Dev} = file:open(TSFile, [write]),
- [io:format(Dev, "~p.~n", [Entry]) || Entry <- TestSpec],
+ {ok,Dev} = file:open(TSFile, [write,{encoding,utf8}]),
+ [io:format(Dev, "~tp.~n", [Entry]) || Entry <- TestSpec],
file:close(Dev),
- io:format("Test specification written to: ~p~n", [TSFile]),
- io:format(user, "Test specification written to: ~p~n", [TSFile]),
+ io:format("Test specification written to: ~tp~n", [TSFile]),
+ io:format(user, "Test specification written to: ~tp~n", [TSFile]),
TSFile.
@@ -267,7 +270,7 @@ run(Opts0, Config) when is_list(Opts0) ->
Override =
fun(O={Key,_}, Os) ->
io:format(user, "ADDING START "
- "OPTION: ~p~n", [O]),
+ "OPTION: ~tp~n", [O]),
[O | lists:keydelete(Key, 1, Os)]
end,
lists:foldl(Override, Opts0, OROpts);
@@ -289,14 +292,14 @@ run(Opts0, Config) when is_list(Opts0) ->
run_ct_run_test(Opts,Config) ->
CTNode = proplists:get_value(ct_node, Config),
Level = proplists:get_value(trace_level, Config),
- test_server:format(Level, "~n[RUN #1] Calling ct:run_test(~p) on ~p~n",
+ test_server:format(Level, "~n[RUN #1] Calling ct:run_test(~tp) on ~p~n",
[Opts, CTNode]),
T0 = erlang:monotonic_time(),
CtRunTestResult = rpc:call(CTNode, ct, run_test, [Opts]),
T1 = erlang:monotonic_time(),
Elapsed = erlang:convert_time_unit(T1-T0, native, milli_seconds),
- test_server:format(Level, "~n[RUN #1] Got return value ~p after ~p ms~n",
+ test_server:format(Level, "~n[RUN #1] Got return value ~tp after ~p ms~n",
[CtRunTestResult,Elapsed]),
case rpc:call(CTNode, erlang, whereis, [ct_util_server]) of
undefined ->
@@ -314,7 +317,7 @@ run_ct_script_start(Opts, Config) ->
CTNode = proplists:get_value(ct_node, Config),
Level = proplists:get_value(trace_level, Config),
Opts1 = [{halt_with,{?MODULE,ct_test_halt}} | Opts],
- test_server:format(Level, "Saving start opts on ~p: ~p~n",
+ test_server:format(Level, "Saving start opts on ~p: ~tp~n",
[CTNode, Opts1]),
rpc:call(CTNode, application, set_env,
[common_test, run_test_start_opts, Opts1]),
@@ -324,7 +327,7 @@ run_ct_script_start(Opts, Config) ->
ExitStatus = rpc:call(CTNode, ct_run, script_start, []),
T1 = erlang:monotonic_time(),
Elapsed = erlang:convert_time_unit(T1-T0, native, milli_seconds),
- test_server:format(Level, "[RUN #2] Got exit status value ~p after ~p ms~n",
+ test_server:format(Level, "[RUN #2] Got exit status value ~tp after ~p ms~n",
[ExitStatus,Elapsed]),
ExitStatus.
@@ -351,6 +354,9 @@ check_result(CtRunTestResult,ExitStatus,Opts)
catch _:_ ->
{error,{unexpected_return_value,{CtRunTestResult,ExitStatus}}}
end;
+check_result(done,0,_Opts) ->
+ %% refresh_logs return
+ ok;
check_result(CtRunTestResult,ExitStatus,_Opts) ->
{error,{unexpected_return_value,{CtRunTestResult,ExitStatus}}}.
@@ -367,12 +373,12 @@ run({M,F,A}, InitCalls, Config) ->
Level = proplists:get_value(trace_level, Config),
lists:foreach(
fun({IM,IF,IA}) ->
- test_server:format(Level, "~nInit call ~w:~w(~p) on ~p...~n",
+ test_server:format(Level, "~nInit call ~w:~tw(~tp) on ~p...~n",
[IM, IF, IA, CTNode]),
Result = rpc:call(CTNode, IM, IF, IA),
- test_server:format(Level, "~n...with result: ~p~n", [Result])
+ test_server:format(Level, "~n...with result: ~tp~n", [Result])
end, InitCalls),
- test_server:format(Level, "~nStarting test with ~w:~w(~p) on ~p~n",
+ test_server:format(Level, "~nStarting test with ~w:~tw(~tp) on ~p~n",
[M, F, A, CTNode]),
rpc:call(CTNode, M, F, A).
@@ -399,7 +405,7 @@ wait_for_ct_stop(Retries, CTNode) ->
Info = (catch process_info(Pid)),
test_server:format(0, "Waiting for CT (~p) to finish (~p)...",
[Pid,Retries]),
- test_server:format(0, "Process info for ~p:~n~p", [Info]),
+ test_server:format(0, "Process info for ~p:~n~tp", [Pid,Info]),
timer:sleep(5000),
wait_for_ct_stop(Retries-1, CTNode)
end.
@@ -409,7 +415,7 @@ wait_for_ct_stop(Retries, CTNode) ->
ct_rpc({M,F,A}, Config) ->
CTNode = proplists:get_value(ct_node, Config),
Level = proplists:get_value(trace_level, Config),
- test_server:format(Level, "~nCalling ~w:~w(~p) on ~p...",
+ test_server:format(Level, "~nCalling ~w:~tw(~tp) on ~p...",
[M,F,A, CTNode]),
rpc:call(CTNode, M, F, A).
@@ -525,7 +531,7 @@ verify_events(TEvs, Evs, Node, Config) ->
verify_events1([TestEv|_], [{TEH,#event{name=stop_logging,node=Node,data=_}}|_], Node, _)
when element(1,TestEv) == TEH, element(2,TestEv) =/= stop_logging ->
- test_server:format("Failed to find ~p in the list of events!~n", [TestEv]),
+ test_server:format("Failed to find ~tp in the list of events!~n", [TestEv]),
exit({event_not_found,TestEv});
verify_events1(TEvs = [TestEv | TestEvs], Evs = [_|Events], Node, Config) ->
@@ -533,8 +539,8 @@ verify_events1(TEvs = [TestEv | TestEvs], Evs = [_|Events], Node, Config) ->
nomatch ->
verify_events1(TEvs, Events, Node, Config);
{'EXIT',Reason} ->
- test_server:format("Failed to find ~p in ~p~n"
- "Reason: ~p~n", [TestEv,Evs,Reason]),
+ test_server:format("Failed to find ~tp in ~tp~n"
+ "Reason: ~tp~n", [TestEv,Evs,Reason]),
exit(Reason);
{Config1,Events1} ->
if is_list(TestEv) ->
@@ -542,13 +548,13 @@ verify_events1(TEvs = [TestEv | TestEvs], Evs = [_|Events], Node, Config) ->
element(1,TestEv) == parallel ; element(1,TestEv) == shuffle ->
ok;
true ->
- test_server:format("Found ~p!", [TestEv])
+ test_server:format("Found ~tp!", [TestEv])
end,
verify_events1(TestEvs, Events1, Node, Config1)
end;
verify_events1([TestEv|_], [], _, _) ->
- test_server:format("Failed to find ~p in the list of events!~n", [TestEv]),
+ test_server:format("Failed to find ~tp in the list of events!~n", [TestEv]),
exit({event_not_found,TestEv});
verify_events1([], Evs, _, Config) ->
@@ -581,8 +587,8 @@ locate(TEvs, Node, Evs, Config) when is_list(TEvs) ->
false ->
nomatch;
true ->
- test_server:format("Found ~p!", [InitStart]),
- test_server:format("Found ~p!", [InitDone]),
+ test_server:format("Found ~tp!", [InitStart]),
+ test_server:format("Found ~tp!", [InitDone]),
verify_events1(TEvs1, Evs1, Node, Config)
end;
_ ->
@@ -630,8 +636,8 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
true
end, Es),
- test_server:format("Found ~p!", [InitStart]),
- test_server:format("Found ~p!", [InitDone]),
+ test_server:format("Found ~tp!", [InitStart]),
+ test_server:format("Found ~tp!", [InitDone]),
{TEs,EvsG};
_ ->
nomatch
@@ -683,10 +689,10 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
[] when Evs2 == [] ->
exit({unmatched,TEv});
[] ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
exit({tc_done_not_found,TEv});
[TcDone|Evs3] ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
RemSize1 = length(Evs3),
if RemSize1 < RemSize ->
{[TcDone|Done],Evs3,RemSize1};
@@ -702,7 +708,7 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
EH == TEH, EvNode == Node, Mod == M,
Func == F, result_match(R, Result)] of
[TcDone|_] ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
{lists:delete(TcDone, Done),RemEvs,RemSize};
[] ->
exit({unmatched,TEv})
@@ -730,7 +736,7 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
[] ->
exit({end_per_group_not_found,TEv});
[_ | RemEvs2] ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
{Done,RemEvs2,length(RemEvs2)}
end;
%% tc_done event for end_per_group
@@ -761,7 +767,7 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
[] ->
exit({end_per_group_not_found,TEv});
[_ | RemEvs2] ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
{Done,RemEvs2,length(RemEvs2)}
end;
%% end_per_group auto- or user skipped
@@ -808,7 +814,7 @@ locate({parallel,TEvs}, Node, Evs, Config) ->
[] ->
exit({unmatched,TEv});
_ ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
Acc
end;
%% start of a sub-group
@@ -861,8 +867,8 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
_ ->
Props = EvProps
end,
- test_server:format("Found ~p!", [InitStart]),
- test_server:format("Found ~p!", [InitDone]),
+ test_server:format("Found ~tp!", [InitStart]),
+ test_server:format("Found ~tp!", [InitDone]),
{TEs,Es};
false ->
nomatch
@@ -903,7 +909,7 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
[_TcStart, TcDone={TEH,#event{name=tc_done,
node=Node,
data={M,F,_}}} | Evs3] ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
RemSize1 = length(Evs3),
if RemSize1 < RemSize ->
{[TcDone|Done],Evs3,RemSize1};
@@ -919,7 +925,7 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
EH == TEH, EvNode == Node, Mod == M,
Func == F, result_match(R, Result)] of
[TcDone|_] ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
{lists:delete(TcDone, Done),RemEvs,RemSize};
[] ->
exit({unmatched,TEv})
@@ -960,7 +966,7 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
_ ->
Props = EvProps1
end,
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
{Done,RemEvs2,length(RemEvs2)}
end;
%% tc_done event for end_per_group
@@ -1004,7 +1010,7 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
_ ->
Props = EvProps1
end,
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
{Done,RemEvs2,length(RemEvs2)}
end;
%% end_per_group auto-or user skipped
@@ -1045,7 +1051,7 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
[] ->
exit({unmatched,TEv});
_ ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
Acc
end;
(TEv={TEH,N,D}, Acc) ->
@@ -1056,7 +1062,7 @@ locate({shuffle,TEvs}, Node, Evs, Config) ->
[] ->
exit({unmatched,TEv});
_ ->
- test_server:format("Found ~p!", [TEv]),
+ test_server:format("Found ~tp!", [TEv]),
Acc
end;
%% start of a sub-group
@@ -1082,8 +1088,8 @@ locate({TEH,Name,{'DEF','RUNDIR'}}, Node, [Ev|Evs], Config) ->
{TEH,#event{name=Name, node=Node, data=EvData}} ->
{_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
D = filename:join(LogDir, "ct_run." ++ atom_to_list(Node)),
- case string:str(EvData, D) of
- 0 -> exit({badmatch,EvData});
+ case string:find(EvData, D) of
+ nomatch -> exit({badmatch,EvData});
_ -> ok
end,
{Config,Evs};
@@ -1098,8 +1104,8 @@ locate({TEH,Name,{'DEF',{'START_TIME','LOGDIR'}}}, Node, [Ev|Evs], Config) ->
{DT={{_,_,_},{_,_,_}},Dir} when is_list(Dir) ->
{_,{_,LogDir}} = lists:keysearch(logdir, 1, get_opts(Config)),
D = filename:join(LogDir, "ct_run." ++ atom_to_list(Node)),
- case string:str(Dir, D) of
- 0 -> exit({badmatch,Dir});
+ case string:find(Dir, D) of
+ nomatch -> exit({badmatch,Dir});
_ -> ok
end,
{[{start_time,DT}|Config],Evs};
@@ -1227,54 +1233,54 @@ result_match(_, _) ->
log_events(TC, Events, EvLogDir, Opts) ->
LogFile = filename:join(EvLogDir, atom_to_list(TC)++".events"),
- {ok,Dev} = file:open(LogFile, [write]),
+ {ok,Dev} = file:open(LogFile, [write,{encoding,utf8}]),
io:format(Dev, "[~n", []),
log_events1(Events, Dev, " "),
file:close(Dev),
FullLogFile = join_abs_dirs(proplists:get_value(net_dir, Opts),
LogFile),
- ct:log("Events written to logfile: <a href=\"file://~s\">~s</a>~n",
+ ct:log("Events written to logfile: <a href=\"file://~ts\">~ts</a>~n",
[FullLogFile,FullLogFile],[no_css]),
- io:format(user, "Events written to logfile: ~p~n", [LogFile]).
+ io:format(user, "Events written to logfile: ~tp~n", [LogFile]).
log_events1(Evs, Dev, "") ->
log_events1(Evs, Dev, " ");
log_events1([E={_EH,tc_start,{_M,{init_per_group,_GrName,Props}}} | Evs], Dev, Ind) ->
case get_prop(Props) of
undefined ->
- io:format(Dev, "~s[~p,~n", [Ind,E]),
+ io:format(Dev, "~s[~tp,~n", [Ind,E]),
log_events1(Evs, Dev, Ind++" ");
Prop ->
- io:format(Dev, "~s{~w,~n~s[~p,~n", [Ind,Prop,Ind++" ",E]),
+ io:format(Dev, "~s{~w,~n~s[~tp,~n", [Ind,Prop,Ind++" ",E]),
log_events1(Evs, Dev, Ind++" ")
end;
log_events1([E={_EH,tc_done,{_M,{init_per_group,_GrName,_Props},_R}} | Evs], Dev, Ind) ->
- io:format(Dev, "~s~p,~n", [Ind,E]),
+ io:format(Dev, "~s~tp,~n", [Ind,E]),
log_events1(Evs, Dev, Ind++" ");
log_events1([E={_EH,tc_start,{_M,{end_per_group,_GrName,_Props}}} | Evs], Dev, Ind) ->
Ind1 = Ind -- " ",
- io:format(Dev, "~s~p,~n", [Ind1,E]),
+ io:format(Dev, "~s~tp,~n", [Ind1,E]),
log_events1(Evs, Dev, Ind1);
log_events1([E={_EH,tc_done,{_M,{end_per_group,_GrName,Props},_R}} | Evs], Dev, Ind) ->
case get_prop(Props) of
undefined ->
- io:format(Dev, "~s~p],~n", [Ind,E]),
+ io:format(Dev, "~s~tp],~n", [Ind,E]),
log_events1(Evs, Dev, Ind--" ");
_Prop ->
- io:format(Dev, "~s~p]},~n", [Ind,E]),
+ io:format(Dev, "~s~tp]},~n", [Ind,E]),
log_events1(Evs, Dev, Ind--" ")
end;
log_events1([E={_EH,tc_auto_skip,{_M,{end_per_group,_GrName},_Reason}} | Evs], Dev, Ind) ->
- io:format(Dev, "~s~p],~n", [Ind,E]),
+ io:format(Dev, "~s~tp],~n", [Ind,E]),
log_events1(Evs, Dev, Ind--" ");
log_events1([E={_EH,tc_user_skip,{_M,{end_per_group,_GrName},_Reason}} | Evs], Dev, Ind) ->
- io:format(Dev, "~s~p],~n", [Ind,E]),
+ io:format(Dev, "~s~tp],~n", [Ind,E]),
log_events1(Evs, Dev, Ind--" ");
log_events1([E], Dev, Ind) ->
- io:format(Dev, "~s~p~n].~n", [Ind,E]),
+ io:format(Dev, "~s~tp~n].~n", [Ind,E]),
ok;
log_events1([E | Evs], Dev, Ind) ->
- io:format(Dev, "~s~p,~n", [Ind,E]),
+ io:format(Dev, "~s~tp,~n", [Ind,E]),
log_events1(Evs, Dev, Ind);
log_events1([], _Dev, _Ind) ->
ok.
@@ -1367,7 +1373,7 @@ delete_dirs(LogDir) ->
Dirs2Del =
lists:foldl(fun(Dir, Del) ->
[S,Mi,H,D,Mo,Y|_] =
- lists:reverse(string:tokens(Dir, [$.,$-,$_])),
+ lists:reverse(string:lexemes(Dir, [$.,$-,$_])),
S2I = fun(Str) -> list_to_integer(Str) end,
DT = {{S2I(Y),S2I(Mo),S2I(D)}, {S2I(H),S2I(Mi),S2I(S)}},
Then = calendar:datetime_to_gregorian_seconds(DT),
@@ -1388,10 +1394,10 @@ delete_dirs(LogDir) ->
delete_dirs(_, []) ->
ok;
delete_dirs(LogDir, [Dir | Dirs]) ->
- test_server:format(0, "Removing old log directory: ~s", [Dir]),
+ test_server:format(0, "Removing old log directory: ~ts", [Dir]),
case catch rm_rec(Dir) of
{_,Reason} ->
- test_server:format(0, "Delete failed! (~p)", [Reason]);
+ test_server:format(0, "Delete failed! (~tp)", [Reason]);
ok ->
ok
end,
diff --git a/lib/common_test/test/ct_test_support_eh.erl b/lib/common_test/test/ct_test_support_eh.erl
index e8db52dcd3..120692dc7c 100644
--- a/lib/common_test/test/ct_test_support_eh.erl
+++ b/lib/common_test/test/ct_test_support_eh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,10 +18,10 @@
%% %CopyrightEnd%
%%
-%%% @doc Event handler module
+%%% Event handler module
%%%
-%%% <p>This is an event handler module used for testing that
-%%% Common Test generates events as expected.</p>
+%%% This is an event handler module used for testing that
+%%% Common Test generates events as expected.
%%%
-module(ct_test_support_eh).
diff --git a/lib/common_test/test/ct_testspec_1_SUITE.erl b/lib/common_test/test/ct_testspec_1_SUITE.erl
index fca5ef3eb3..2d2c42999f 100644
--- a/lib/common_test/test/ct_testspec_1_SUITE.erl
+++ b/lib/common_test/test/ct_testspec_1_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -616,7 +616,7 @@ setup_and_execute(TCName, TestSpec, Config) ->
FullSpecFile = ct_test_support:join_abs_dirs(?config(net_dir, Opts),
SpecFile),
- io:format("~nTest spec created here~n~n<a href=\"file://~s\">~s</a>~n",
+ io:format("~nTest spec created here~n~n<a href=\"file://~ts\">~ts</a>~n",
[FullSpecFile,FullSpecFile]),
ok = ct_test_support:run(Opts, Config),
@@ -638,8 +638,8 @@ setup_and_execute(TCName, TestSpec, Config) ->
create_spec_file(SpecDir, TCName, TestSpec) ->
FileName = filename:join(SpecDir,
atom_to_list(TCName)++".spec"),
- {ok,Dev} = file:open(FileName, [write]),
- [io:format(Dev, "~p.~n", [Term]) || Term <- TestSpec],
+ {ok,Dev} = file:open(FileName, [write,{encoding,utf8}]),
+ [io:format(Dev, "~tp.~n", [Term]) || Term <- TestSpec],
file:close(Dev),
FileName.
diff --git a/lib/common_test/test/ct_unicode_SUITE.erl b/lib/common_test/test/ct_unicode_SUITE.erl
new file mode 100644
index 0000000000..6f6ec97ceb
--- /dev/null
+++ b/lib/common_test/test/ct_unicode_SUITE.erl
@@ -0,0 +1,218 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2017. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File: ct_unicode_SUITE
+%%%
+%%% Description:
+%%% Test that common_test handles and logs unicode strings and atoms
+%%% correctly.
+%%%
+%%% The suite used for the test is located in the data directory.
+%%%-------------------------------------------------------------------
+-module(ct_unicode_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+-include_lib("common_test/include/ct_event.hrl").
+
+-define(eh, ct_test_support_eh).
+
+%%--------------------------------------------------------------------
+%% TEST SERVER CALLBACK FUNCTIONS
+%%--------------------------------------------------------------------
+
+%%--------------------------------------------------------------------
+%% Description: Since Common Test starts another Test Server
+%% instance, the tests need to be performed on a separate node (or
+%% there will be clashes with logging processes etc).
+%%--------------------------------------------------------------------
+init_per_suite(Config) ->
+ case file:native_name_encoding() of
+ latin1 -> {skip,"Test is not applicable on latin1 file system"};
+ _ ->
+ ct_test_support:init_per_suite([{printable_range,unicode}|Config])
+ end.
+
+end_per_suite(Config) ->
+ ct_test_support:end_per_suite(Config).
+
+init_per_testcase(TestCase, Config) ->
+ ct_test_support:init_per_testcase(TestCase, Config).
+
+end_per_testcase(TestCase, Config) ->
+ ct_test_support:end_per_testcase(TestCase, Config).
+
+suite() -> [].
+
+all() ->
+ [unicode_atoms_SUITE,
+ unicode_spec].
+
+%%--------------------------------------------------------------------
+%% TEST CASES
+%%--------------------------------------------------------------------
+unicode_atoms_SUITE(Config) ->
+ DataDir = ?config(data_dir,Config),
+ PrivDir = ?config(priv_dir,Config),
+ run_test(unicode_atoms_SUITE,
+ [{dir,DataDir},{suite,unicode_atoms_SUITE}], Config).
+
+unicode_spec(Config) ->
+ DataDir = ?config(data_dir,Config),
+ PrivDir = ?config(priv_dir,Config),
+ CfgName = "unicode_αβ.cfg",
+ Cfg = io_lib:format("{~tw,[{~tw,\"~ts\"}]}.~n",
+ ['key_αβ','subkey_αβ',"value_αβ"]),
+ ok = file:write_file(filename:join(PrivDir,CfgName),
+ unicode:characters_to_binary(Cfg)),
+ TestSpec = [{cases, DataDir, unicode_atoms_SUITE, ['config_αβ']},
+ {config, PrivDir, CfgName}],
+ TestSpecName = ct_test_support:write_testspec(TestSpec, PrivDir,
+ "unicode_αβ.spec"),
+ run_test(unicode_spec,[{spec,TestSpecName}],Config).
+
+%%%-----------------------------------------------------------------
+%%% HELP FUNCTIONS
+%%%-----------------------------------------------------------------
+run_test(Label, Test, Config) ->
+ {Opts,ERPid} = setup_env([{label,Label}|Test], Config),
+ ok = ct_test_support:run(Opts, Config),
+ TestEvents = ct_test_support:get_events(ERPid, Config),
+ ct_test_support:log_events(Label,
+ reformat_events(TestEvents, ?eh),
+ ?config(priv_dir, Config),
+ Opts),
+ ExpEvents = events_to_check(Label),
+ ok = ct_test_support:verify_events(ExpEvents, TestEvents, Config),
+ check_logs([_,_]=get_log_dirs(TestEvents)).
+
+setup_env(Test, Config) ->
+ Opts0 = ct_test_support:get_opts(Config),
+ Level = ?config(trace_level, Config),
+ EvHArgs = [{cbm,ct_test_support},{trace_level,Level}],
+ Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}} | Test],
+ ERPid = ct_test_support:start_event_receiver(Config),
+ {Opts,ERPid}.
+
+reformat_events(Events, EH) ->
+ ct_test_support:reformat(Events, EH).
+
+get_log_dirs([{?eh,#event{name=start_logging,data=LogDir}}|Events]) ->
+ [LogDir|get_log_dirs(Events)];
+get_log_dirs([_|Events]) ->
+ get_log_dirs(Events);
+get_log_dirs([]) ->
+ [].
+
+%%%-----------------------------------------------------------------
+%%% TEST EVENTS
+%%%-----------------------------------------------------------------
+events_to_check(Test) ->
+ %% 2 tests (ct:run_test + script_start) is default
+ events_to_check(Test, 2).
+
+events_to_check(_, 0) ->
+ [];
+events_to_check(Test, N) ->
+ test_events(Test) ++ events_to_check(Test, N-1).
+
+test_events(unicode_atoms_SUITE) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,6}},
+ {?eh,tc_start,{unicode_atoms_SUITE,init_per_suite}},
+ {?eh,tc_done,{unicode_atoms_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{unicode_atoms_SUITE,'test_αβ'}},
+ {?eh,tc_done,{unicode_atoms_SUITE,'test_αβ',ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{unicode_atoms_SUITE,'fail_αβ_1'}},
+ {?eh,tc_done,{unicode_atoms_SUITE,'fail_αβ_1','_'}},
+ {?eh,test_stats,{1,1,{0,0}}},
+ {?eh,tc_start,{unicode_atoms_SUITE,'fail_αβ_2'}},
+ {?eh,tc_done,{unicode_atoms_SUITE,'fail_αβ_2','_'}},
+ {?eh,test_stats,{1,2,{0,0}}},
+ {?eh,tc_start,{unicode_atoms_SUITE,'fail_αβ_3'}},
+ {?eh,tc_done,{unicode_atoms_SUITE,'fail_αβ_3','_'}},
+ {?eh,test_stats,{1,3,{0,0}}},
+ {?eh,tc_start,{unicode_atoms_SUITE,'fail_αβ_4'}},
+ {?eh,tc_done,{unicode_atoms_SUITE,'fail_αβ_4','_'}},
+ {?eh,test_stats,{1,4,{0,0}}},
+ {?eh,tc_start,{unicode_atoms_SUITE,'skip_αβ'}},
+ {?eh,tc_done,{unicode_atoms_SUITE,'skip_αβ','_'}},
+ {?eh,test_stats,{1,4,{1,0}}},
+ {?eh,tc_start,{unicode_atoms_SUITE,end_per_suite}},
+ {?eh,tc_done,{unicode_atoms_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ];
+test_events(unicode_spec) ->
+ [
+ {?eh,start_logging,{'DEF','RUNDIR'}},
+ {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}},
+ {?eh,start_info,{1,1,1}},
+ {?eh,tc_start,{unicode_atoms_SUITE,init_per_suite}},
+ {?eh,tc_done,{unicode_atoms_SUITE,init_per_suite,ok}},
+ {?eh,tc_start,{unicode_atoms_SUITE,'config_αβ'}},
+ {?eh,tc_done,{unicode_atoms_SUITE,'config_αβ',ok}},
+ {?eh,test_stats,{1,0,{0,0}}},
+ {?eh,tc_start,{unicode_atoms_SUITE,end_per_suite}},
+ {?eh,tc_done,{unicode_atoms_SUITE,end_per_suite,ok}},
+ {?eh,test_done,{'DEF','STOP_TIME'}},
+ {?eh,stop_logging,[]}
+ ].
+
+%%%-----------------------------------------------------------------
+%%% Check logs for escaped unicode characters
+check_logs(Dirs) ->
+ ct:log("Checking logs for escaped unicode characters (αβ).~nDirs:~n~tp",
+ [Dirs]),
+ {ok,RE} = re:compile(<<"x{3B[12]}"/utf8>>),
+ case check_logs1(RE,Dirs,[]) of
+ [] ->
+ ok;
+ Match ->
+ MatchStr = lists:join("\n",Match),
+ ct:log("ERROR: Escaped unicode characters found in:~n~ts",[MatchStr]),
+ ct:fail(escaped_unicode_characters_found)
+ end.
+
+check_logs1(RE,[F|Fs],Match) ->
+ New = case filelib:is_dir(F) of
+ true ->
+ {ok,Files} = file:list_dir(F),
+ check_logs1(RE,[filename:join(F,File)||File<-Files],[]);
+ false ->
+ check_log(RE,F)
+ end,
+ check_logs1(RE,Fs,New++Match);
+check_logs1(_RE,[],Match) ->
+ Match.
+
+check_log(RE,F) ->
+ {ok,Bin} = file:read_file(F),
+ case re:run(Bin,RE,[{capture,none}]) of
+ match ->
+ [F];
+ nomatch ->
+ []
+ end.
diff --git a/lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl b/lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl
new file mode 100644
index 0000000000..4f9dd20e3e
--- /dev/null
+++ b/lib/common_test/test/ct_unicode_SUITE_data/unicode_atoms_SUITE.erl
@@ -0,0 +1,98 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009-2018. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(unicode_atoms_SUITE).
+
+-compile(export_all).
+
+-include_lib("common_test/include/ct.hrl").
+
+suite() ->
+ [{timetrap,{seconds,30}}].
+
+init_per_suite(Config) ->
+ Config.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, _Config) ->
+ ok.
+
+init_per_testcase(_TestCase, Config) ->
+ Config.
+
+end_per_testcase(_TestCase, _Config) ->
+ ok.
+
+groups() ->
+ [].
+
+all() ->
+ ['test_αβ',
+ 'fail_αβ_1',
+ 'fail_αβ_2',
+ 'fail_αβ_3',
+ 'fail_αβ_4',
+ 'skip_αβ'].
+
+'test_αβ'(_Config) ->
+ ct:log("This is test case ~tw",[?FUNCTION_NAME]),
+ ok.
+
+'fail_αβ_1'(_Config) ->
+ ct:log("This is test case ~tw",[?FUNCTION_NAME]),
+ 'α' = 'β',
+ ok.
+
+'fail_αβ_2'(_Config) ->
+ ct:log("This is test case ~tw",[?FUNCTION_NAME]),
+ ct:fail({failing,testcase,?FUNCTION_NAME}),
+ ok.
+
+'fail_αβ_3'(_Config) ->
+ ct:log("This is test case ~tw",[?FUNCTION_NAME]),
+ exit({exiting,testcase,?FUNCTION_NAME}),
+ ok.
+
+'fail_αβ_4'(_Config) ->
+ ct:log("This is test case ~tw",[?FUNCTION_NAME]),
+ S = try throw(ok) catch throw:ok:Stacktrace -> Stacktrace end,
+ erlang:raise(error,{error,testcase,?FUNCTION_NAME},S),
+ ok.
+
+'skip_αβ'(_Config) ->
+ ct:log("This is test case ~tw",[?FUNCTION_NAME]),
+ {skip,"Skipping " ++ atom_to_list(?FUNCTION_NAME)}.
+
+
+%% This should not be listed in all/0. It is only to be run explicitly
+%% using a test spec where the config file is declared as well.
+'config_αβ'() ->
+ [{require,'alias_αβ','key_αβ'}].
+'config_αβ'(_Config) ->
+ ct:log("This is test case ~tw",[?FUNCTION_NAME]),
+ Conf = ct:get_config('alias_αβ'),
+ Conf = ct:get_config('key_αβ'),
+ ct:log("Required config: ~tp",[Conf]),
+ ok.
diff --git a/lib/common_test/test/ct_userconfig_callback.erl b/lib/common_test/test/ct_userconfig_callback.erl
index c723f4ca1c..e48d338dd5 100644
--- a/lib/common_test/test/ct_userconfig_callback.erl
+++ b/lib/common_test/test/ct_userconfig_callback.erl
@@ -1,7 +1,7 @@
%%--------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@
-export([check_parameter/1, read_config/1]).
read_config(Str) ->
- KeyVals = string:tokens(Str, " "),
+ KeyVals = string:lexemes(Str, " "),
{ok,read_config1(KeyVals)}.
read_config1([Key,Val | KeyVals]) ->
diff --git a/lib/common_test/test/ct_verbosity_SUITE.erl b/lib/common_test/test/ct_verbosity_SUITE.erl
index b9298e54ca..095cd1b70b 100644
--- a/lib/common_test/test/ct_verbosity_SUITE.erl
+++ b/lib/common_test/test/ct_verbosity_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -47,8 +47,8 @@
init_per_suite(Config) ->
DataDir = ?config(data_dir, Config),
EvH = filename:join(DataDir,"simple_evh.erl"),
- ct:pal("Compiling ~s: ~p", [EvH,compile:file(EvH,[{outdir,DataDir},
- debug_info])]),
+ ct:pal("Compiling ~ts: ~p", [EvH,compile:file(EvH,[{outdir,DataDir},
+ debug_info])]),
ct_test_support:init_per_suite([{path_dirs,[DataDir]} | Config]).
end_per_suite(Config) ->
diff --git a/lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl b/lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl
index 03a0832e53..d1c293b4af 100644
--- a/lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl
+++ b/lib/common_test/test/ct_verbosity_SUITE_data/simple_evh.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,14 +18,14 @@
%% %CopyrightEnd%
%%
-%%% @doc Common Test Framework Event Handler
+%%% Common Test Framework Event Handler
%%%
-%%% <p>This module implements an event handler that CT uses to
+%%% This module implements an event handler that CT uses to
%%% handle status and progress notifications during test runs.
%%% The notifications are handled locally (per node) and passed
%%% on to ct_master when CT runs in distributed mode. This
%%% module may be used as a template for other event handlers
-%%% that can be plugged in to handle local logging and reporting.</p>
+%%% that can be plugged in to handle local logging and reporting.
-module(simple_evh).
-behaviour(gen_event).
diff --git a/lib/common_test/test/erl2html2_SUITE.erl b/lib/common_test/test/erl2html2_SUITE.erl
index bdce43c9c9..b2336ff0bc 100644
--- a/lib/common_test/test/erl2html2_SUITE.erl
+++ b/lib/common_test/test/erl2html2_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2012-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -163,9 +163,9 @@ convert_module(Mod,InclDirs,Config) ->
PrivDir = ?config(priv_dir,Config),
Src = filename:join(DataDir,Mod++".erl"),
Dst = filename:join(PrivDir,Mod++".erl.html"),
- io:format("<a href=\"~s\">~s</a>\n",[Src,filename:basename(Src)]),
+ io:format("<a href=\"~ts\">~s</a>\n",[Src,filename:basename(Src)]),
ok = erl2html2:convert(Src, Dst, InclDirs, "<html><body>"),
- io:format("<a href=\"~s\">~s</a>\n",[Dst,filename:basename(Dst)]),
+ io:format("<a href=\"~ts\">~s</a>\n",[Dst,filename:basename(Dst)]),
{Src,Dst}.
%% Check that there are the same number of lines in each file, and
@@ -214,10 +214,10 @@ check_line_number(Last,Line,OrigLine) ->
[$>|Rest] = lists:dropwhile(fun($>) -> false; (_) -> true end,Line),
check_line_number(Last,Rest,OrigLine);
_ ->
- [N |_] = string:tokens(Line,":"),
+ [N |_] = string:lexemes(Line,":"),
% erlang:display(N),
Num =
- try list_to_integer(string:strip(N))
+ try list_to_integer(string:trim(N,both,"\s"))
catch _:_ -> ct:fail({no_line_number_after,Last,OrigLine})
end,
if Num == Last+1 ->
diff --git a/lib/common_test/test/telnet_server.erl b/lib/common_test/test/telnet_server.erl
index 65300b0bdf..cef7784333 100644
--- a/lib/common_test/test/telnet_server.erl
+++ b/lib/common_test/test/telnet_server.erl
@@ -249,7 +249,7 @@ do_handle_data("echo " ++ Data,State) ->
send(Data++"\r\n> ",State),
{ok,State};
do_handle_data("echo_sep " ++ Data,State) ->
- Msgs = string:tokens(Data," "),
+ Msgs = string:lexemes(Data," "),
lists:foreach(fun(Msg) ->
send(Msg,State),
timer:sleep(10)
@@ -260,28 +260,28 @@ do_handle_data("echo_no_prompt " ++ Data,State) ->
send(Data,State),
{ok,State};
do_handle_data("echo_ml " ++ Data,State) ->
- Lines = string:tokens(Data," "),
- ReturnData = string:join(Lines,"\n"),
+ Lines = string:lexemes(Data," "),
+ ReturnData = lists:flatten(lists:join("\n",Lines)),
send(ReturnData++"\r\n> ",State),
{ok,State};
do_handle_data("echo_ml_no_prompt " ++ Data,State) ->
- Lines = string:tokens(Data," "),
- ReturnData = string:join(Lines,"\n"),
+ Lines = string:lexemes(Data," "),
+ ReturnData = lists:flatten(lists:join("\n",Lines)),
send(ReturnData,State),
{ok,State};
do_handle_data("echo_loop " ++ Data,State) ->
- [TStr|Lines] = string:tokens(Data," "),
- ReturnData = string:join(Lines,"\n"),
+ [TStr|Lines] = string:lexemes(Data," "),
+ ReturnData = lists:flatten(lists:join("\n",Lines)),
send_loop(list_to_integer(TStr),ReturnData,State),
{ok,State};
do_handle_data("echo_delayed_prompt "++Data,State) ->
- [MsStr|EchoData] = string:tokens(Data, " "),
- send(string:join(EchoData,"\n"),State),
+ [MsStr|EchoData] = string:lexemes(Data, " "),
+ send(lists:flatten(lists:join("\n",EchoData)),State),
timer:sleep(list_to_integer(MsStr)),
send("\r\n> ",State),
{ok,State};
do_handle_data("disconnect_after " ++WaitStr,State) ->
- Wait = list_to_integer(string:strip(WaitStr,right,$\n)),
+ Wait = list_to_integer(string:trim(WaitStr,trailing,"\n")),
dbg("Server will close connection in ~w ms...", [Wait]),
erlang:send_after(Wait,self(),disconnect),
{ok,State};
diff --git a/lib/common_test/test/test_server_SUITE.erl b/lib/common_test/test/test_server_SUITE.erl
index 50d8bdd1ac..05737cfac9 100644
--- a/lib/common_test/test/test_server_SUITE.erl
+++ b/lib/common_test/test/test_server_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2010-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -18,12 +18,7 @@
%% %CopyrightEnd%
%%
%%%-------------------------------------------------------------------
-%%% @author Lukas Larsson <[email protected]>
-%%% @copyright (C) 2011, Erlang Solutions Ltd.
-%%% @doc
-%%%
-%%% @end
-%%% Created : 15 Feb 2011 by Lukas Larsson <[email protected]>
+%%% Author: Lukas Larsson <[email protected]>
%%%-------------------------------------------------------------------
-module(test_server_SUITE).
@@ -71,7 +66,7 @@ init_per_testcase(_TestCase, Config) ->
%% @spec end_per_testcase(TestCase, Config0) ->
%% void() | {save_config,Config1} | {fail,Reason}
end_per_testcase(test_server_unicode, _Config) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
N1 = list_to_atom("test_server_tester_latin1" ++ "@" ++ Host),
N2 = list_to_atom("test_server_tester_utf8" ++ "@" ++ Host),
test_server:stop_node(N1),
@@ -347,7 +342,7 @@ generate_and_run_unicode_test(Config0,Encoding) ->
RunDir = get_latest_run_dir(LogDir),
true = filelib:is_dir(RunDir),
- LowerModStr = string:to_lower(ModStr),
+ LowerModStr = string:lowercase(ModStr),
SuiteHtml = translate_filename(LowerModStr++".src.html",Encoding),
true = filelib:is_regular(filename:join(RunDir,SuiteHtml)),
@@ -362,7 +357,7 @@ generate_and_run_unicode_test(Config0,Encoding) ->
%% remote file system on master - i.e. they will use same file name
%% mode as the master.
start_node(Config,Name,Args) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
ct:log("Trying to start ~w@~s~n",[Name,Host]),
case test_server:start_node(Name, peer, [{args,Args}]) of
{error,Reason} ->
diff --git a/lib/common_test/test/test_server_test_lib.erl b/lib/common_test/test/test_server_test_lib.erl
index cf5951ae03..9ee946af0b 100644
--- a/lib/common_test/test/test_server_test_lib.erl
+++ b/lib/common_test/test/test_server_test_lib.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2016. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2017. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
@@ -43,7 +43,7 @@ pre_init_per_testcase(_TC,Config,State) ->
{start_slave(Config, 50),State}.
start_slave(Config,_Level) ->
- [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ [_,Host] = string:lexemes(atom_to_list(node()), "@"),
ct:log("Trying to start ~s~n",
["test_server_tester@"++Host]),
@@ -81,7 +81,7 @@ prepare_tester_node(Node,Config) ->
[true = rpc:call(Node, code, add_patha, [D]) || D <- PathDirs],
io:format("Dirs added to code path (on ~w):~n",
[Node]),
- [io:format("~s~n", [D]) || D <- PathDirs],
+ [io:format("~ts~n", [D]) || D <- PathDirs],
true = rpc:call(Node, os, putenv,
["TEST_SERVER_FRAMEWORK", "undefined"]),
@@ -121,7 +121,7 @@ parse_suite(FileName) ->
end.
fline(Fd) ->
- case prim_file:read_line(Fd) of
+ case file:read_line(Fd) of
eof -> eof;
{ok, Line} -> Line
end.