diff options
Diffstat (limited to 'lib/common_test/test')
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 = "<" ++ string:substr(StrPid, 2, length(StrPid)-2) ++ ">",  +    EscPid = "<" ++ string:slice(StrPid, 1, length(StrPid)-2) ++ ">",       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. | 
