diff options
Diffstat (limited to 'lib/tools/test')
-rw-r--r-- | lib/tools/test/Makefile | 1 | ||||
-rw-r--r-- | lib/tools/test/cover_SUITE.erl | 250 | ||||
-rw-r--r-- | lib/tools/test/cover_SUITE_data/compile_beam/v.erl | 7 | ||||
-rw-r--r-- | lib/tools/test/cover_SUITE_data/compile_beam/z.erl | 1 | ||||
-rw-r--r-- | lib/tools/test/cover_SUITE_data/f.erl | 11 | ||||
-rw-r--r-- | lib/tools/test/cprof_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/tools/test/emacs_SUITE.erl | 76 | ||||
-rw-r--r-- | lib/tools/test/xref_SUITE.erl | 65 |
8 files changed, 333 insertions, 80 deletions
diff --git a/lib/tools/test/Makefile b/lib/tools/test/Makefile index 86c81217b6..484cfdf53f 100644 --- a/lib/tools/test/Makefile +++ b/lib/tools/test/Makefile @@ -22,6 +22,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk MODULES = \ cover_SUITE \ eprof_SUITE \ + emacs_SUITE \ emem_SUITE \ fprof_SUITE \ cprof_SUITE \ diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl index c2c708d806..5abc5c41b1 100644 --- a/lib/tools/test/cover_SUITE.erl +++ b/lib/tools/test/cover_SUITE.erl @@ -23,7 +23,9 @@ init_per_group/2,end_per_group/2]). -export([start/1, compile/1, analyse/1, misc/1, stop/1, - distribution/1, export_import/1, + distribution/1, reconnect/1, die_and_reconnect/1, + dont_reconnect_after_stop/1, stop_node_after_disconnect/1, + export_import/1, otp_5031/1, eif/1, otp_5305/1, otp_5418/1, otp_6115/1, otp_7095/1, otp_8188/1, otp_8270/1, otp_8273/1, otp_8340/1]). @@ -45,7 +47,9 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> case whereis(cover_server) of undefined -> - [start, compile, analyse, misc, stop, distribution, + [start, compile, analyse, misc, stop, + distribution, reconnect, die_and_reconnect, + dont_reconnect_after_stop, stop_node_after_disconnect, export_import, otp_5031, eif, otp_5305, otp_5418, otp_6115, otp_7095, otp_8188, otp_8270, otp_8273, otp_8340]; @@ -85,8 +89,11 @@ init_per_testcase(TC, Config) when TC =:= misc; init_per_testcase(_TestCase, Config) -> Config. -end_per_testcase(_TestCase, _Config) -> - %cover:stop(), +end_per_testcase(TestCase, _Config) -> + case lists:member(TestCase,[start,compile,analyse,misc]) of + true -> ok; + false -> cover:stop() + end, ok. start(suite) -> []; @@ -142,7 +149,9 @@ compile(Config) when is_list(Config) -> ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)), {ok,crypt} = cover:compile_beam("crypt.beam") end, + Path = filename:join([?config(data_dir, Config), "compile_beam", "v.erl"]), ?line {ok,v} = cover:compile_beam(v), + {source,Path} = lists:keyfind(source, 1, v:module_info(compile)), ?line {ok,w} = cover:compile_beam("w.beam"), ?line {error,{no_abstract_code,"./x.beam"}} = cover:compile_beam(x), ?line {error,{already_cover_compiled,no_beam_found,a}}=cover:compile_beam(a), @@ -270,12 +279,23 @@ analyse(Config) when is_list(Config) -> ?line f:f2(), ?line {ok, "f.COVER.out"} = cover:analyse_to_file(f), - %% Source code cannot be found by analyse_to_file + %% Source code can be found via source ?line {ok,v} = compile:file("compile_beam/v",[debug_info]), ?line code:purge(v), ?line {module,v} = code:load_file(v), ?line {ok,v} = cover:compile_beam(v), - ?line {error,no_source_code_found} = cover:analyse_to_file(v), + {ok,"v.COVER.out"} = cover:analyse_to_file(v), + + %% Source code cannot be found + {ok,_} = file:copy("compile_beam/z.erl", "z.erl"), + {ok,z} = compile:file(z,[debug_info]), + code:purge(z), + {module,z} = code:load_file(z), + {ok,z} = cover:compile_beam(z), + ok = file:delete("z.erl"), + {error,no_source_code_found} = cover:analyse_to_file(z), + code:purge(z), + code:delete(z), ?line {error,{not_cover_compiled,b}} = cover:analyse(b), ?line {error,{not_cover_compiled,g}} = cover:analyse(g), @@ -326,14 +346,16 @@ distribution(Config) when is_list(Config) -> ?line {ok,N1} = ?t:start_node(cover_SUITE_distribution1,slave,[]), ?line {ok,N2} = ?t:start_node(cover_SUITE_distribution2,slave,[]), ?line {ok,N3} = ?t:start_node(cover_SUITE_distribution3,slave,[]), + ?line {ok,N4} = ?t:start_node(cover_SUITE_distribution4,slave,[]), %% Check that an already compiled module is loaded on new nodes ?line {ok,f} = cover:compile(f), - ?line {ok,[_,_,_]} = cover:start(nodes()), + ?line {ok,[_,_,_,_]} = cover:start(nodes()), ?line cover_compiled = code:which(f), ?line cover_compiled = rpc:call(N1,code,which,[f]), ?line cover_compiled = rpc:call(N2,code,which,[f]), ?line cover_compiled = rpc:call(N3,code,which,[f]), + ?line cover_compiled = rpc:call(N4,code,which,[f]), %% Check that a node cannot be started twice ?line {ok,[]} = cover:start(N2), @@ -351,6 +373,7 @@ distribution(Config) when is_list(Config) -> ?line cover_compiled = rpc:call(N1,code,which,[v]), ?line cover_compiled = rpc:call(N2,code,which,[v]), ?line cover_compiled = rpc:call(N3,code,which,[v]), + ?line cover_compiled = rpc:call(N4,code,which,[v]), %% this is lost when the node is killed ?line rpc:call(N3,f,f2,[]), @@ -385,6 +408,18 @@ distribution(Config) when is_list(Config) -> %% reset on the remote node(s)) ?line check_f_calls(1,1), + %% Another checn that data is not fetched twice, i.e. when flushed + %% then analyse should not add the same data again. + ?line rpc:call(N4,f,f2,[]), + ?line ok = cover:flush(N4), + ?line check_f_calls(1,2), + + %% Check that flush collects data so calls are not lost if node is killed + ?line rpc:call(N4,f,f2,[]), + ?line ok = cover:flush(N4), + ?line rpc:call(N4,erlang,halt,[]), + ?line check_f_calls(1,3), + %% Check that stop() unloads on all nodes ?line ok = cover:stop(), ?line timer:sleep(100), %% Give nodes time to unload on slow machines. @@ -393,20 +428,205 @@ distribution(Config) when is_list(Config) -> ?line true = is_unloaded(LocalBeam), ?line true = is_unloaded(N2Beam), - %% Check that cover_server on remote node dies if main node dies + %% Check that cover_server on remote node does not die if main node dies ?line {ok,[N1]} = cover:start(N1), - ?line true = is_pid(rpc:call(N1,erlang,whereis,[cover_server])), + ?line true = is_pid(N1Server = rpc:call(N1,erlang,whereis,[cover_server])), ?line exit(whereis(cover_server),kill), - ?line timer:sleep(10), - ?line undefined = rpc:call(N1,erlang,whereis,[cover_server]), - + ?line timer:sleep(100), + ?line N1Server = rpc:call(N1,erlang,whereis,[cover_server]), + %% Cleanup ?line Files = lsfiles(), ?line remove(files(Files, ".beam")), ?line ?t:stop_node(N1), ?line ?t:stop_node(N2). - +%% Test that a lost node is reconnected +reconnect(Config) -> + DataDir = ?config(data_dir, Config), + ok = file:set_cwd(DataDir), + + {ok,a} = compile:file(a), + {ok,b} = compile:file(b), + {ok,f} = compile:file(f), + + {ok,N1} = ?t:start_node(cover_SUITE_reconnect,peer, + [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,a} = cover:compile(a), + {ok,f} = cover:compile(f), + {ok,[N1]} = cover:start(nodes()), + + %% Some calls to check later + rpc:call(N1,f,f1,[]), + cover:flush(N1), + rpc:call(N1,f,f1,[]), + + %% This will cause a call to f:f2() when nodes()==[] on N1 + rpc:cast(N1,f,call_f2_when_isolated,[]), + + %% Disconnect and check that node is removed from main cover node + net_kernel:disconnect(N1), + timer:sleep(500), % allow some to detect disconnect and for f:f2() call + [] = cover:which_nodes(), + + %% Do some add one module (b) and remove one module (a) + code:purge(a), + {module,a} = code:load_file(a), + {ok,b} = cover:compile(b), + cover_compiled = code:which(b), + + [] = cover:which_nodes(), + check_f_calls(1,0), % only the first call - before the flush + + %% Reconnect the node and check that b and f are cover compiled but not a + net_kernel:connect_node(N1), + timer:sleep(100), + [N1] = cover:which_nodes(), % we are reconnected + cover_compiled = rpc:call(N1,code,which,[b]), + cover_compiled = rpc:call(N1,code,which,[f]), + ABeam = rpc:call(N1,code,which,[a]), + false = (cover_compiled==ABeam), + + %% Ensure that we have: + %% * one f1 call from before the flush, + %% * one f1 call from after the flush but before disconnect + %% * one f2 call when disconnected + check_f_calls(2,1), + + cover:stop(), + ?t:stop_node(N1), + ok. + +%% Test that a lost node is reconnected - also if it has been dead +die_and_reconnect(Config) -> + DataDir = ?config(data_dir, Config), + ok = file:set_cwd(DataDir), + + {ok,f} = compile:file(f), + + NodeName = cover_SUITE_die_and_reconnect, + {ok,N1} = ?t:start_node(NodeName,peer, + [{args," -pa " ++ DataDir},{start_cover,false}]), + %% {ok,a} = cover:compile(a), + {ok,f} = cover:compile(f), + {ok,[N1]} = cover:start(nodes()), + + %% Some calls to check later + rpc:call(N1,f,f1,[]), + cover:flush(N1), + rpc:call(N1,f,f1,[]), + + %% Kill the node + rpc:call(N1,erlang,halt,[]), + [] = cover:which_nodes(), + + check_f_calls(1,0), % only the first call - before the flush + + %% Restart the node and check that cover reconnects + {ok,N1} = ?t:start_node(NodeName,peer, + [{args," -pa " ++ DataDir},{start_cover,false}]), + timer:sleep(100), + [N1] = cover:which_nodes(), % we are reconnected + cover_compiled = rpc:call(N1,code,which,[f]), + + %% One more call... + rpc:call(N1,f,f1,[]), + + %% Ensure that no more calls are counted + check_f_calls(2,0), + + cover:stop(), + ?t:stop_node(N1), + ok. + +%% Test that a stopped node is not marked as lost, i.e. that it is not +%% reconnected if it is restarted (OTP-10638) +dont_reconnect_after_stop(Config) -> + DataDir = ?config(data_dir, Config), + ok = file:set_cwd(DataDir), + + {ok,f} = compile:file(f), + + NodeName = cover_SUITE_dont_reconnect_after_stop, + {ok,N1} = ?t:start_node(NodeName,peer, + [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,f} = cover:compile(f), + {ok,[N1]} = cover:start(nodes()), + + %% A call to check later + rpc:call(N1,f,f1,[]), + + %% Stop cover on the node, then terminate the node + cover:stop(N1), + rpc:call(N1,erlang,halt,[]), + [] = cover:which_nodes(), + + check_f_calls(1,0), + + %% Restart the node and check that cover does not reconnect + {ok,N1} = ?t:start_node(NodeName,peer, + [{args," -pa " ++ DataDir},{start_cover,false}]), + timer:sleep(300), + [] = cover:which_nodes(), + Beam = rpc:call(N1,code,which,[f]), + false = (Beam==cover_compiled), + + %% One more call... + rpc:call(N1,f,f1,[]), + cover:flush(N1), + + %% Ensure that the last call is not counted + check_f_calls(1,0), + + cover:stop(), + ?t:stop_node(N1), + ok. + +%% Test that a node which is stopped while it is marked as lost is not +%% reconnected if it is restarted (OTP-10638) +stop_node_after_disconnect(Config) -> + DataDir = ?config(data_dir, Config), + ok = file:set_cwd(DataDir), + + {ok,f} = compile:file(f), + + NodeName = cover_SUITE_stop_node_after_disconnect, + {ok,N1} = ?t:start_node(NodeName,peer, + [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,f} = cover:compile(f), + {ok,[N1]} = cover:start(nodes()), + + %% A call to check later + rpc:call(N1,f,f1,[]), + + %% Flush the node, then terminate the node to make it marked as lost + cover:flush(N1), + rpc:call(N1,erlang,halt,[]), + + check_f_calls(1,0), + + %% Stop cover on node + cover:stop(N1), + + %% Restart the node and check that cover does not reconnect + {ok,N1} = ?t:start_node(NodeName,peer, + [{args," -pa " ++ DataDir},{start_cover,false}]), + timer:sleep(300), + [] = cover:which_nodes(), + Beam = rpc:call(N1,code,which,[f]), + false = (Beam==cover_compiled), + + %% One more call... + rpc:call(N1,f,f1,[]), + cover:flush(N1), + + %% Ensure that the last call is not counted + check_f_calls(1,0), + + cover:stop(), + ?t:stop_node(N1), + ok. + export_import(suite) -> []; export_import(Config) when is_list(Config) -> ?line DataDir = ?config(data_dir, Config), @@ -795,7 +1015,7 @@ otp_8270(Config) when is_list(Config) -> ok. otp_8273(doc) -> - ["OTP-8270. Bug."]; + ["OTP-8273. Bug."]; otp_8273(suite) -> []; otp_8273(Config) when is_list(Config) -> Test = <<"-module(t). @@ -1238,4 +1458,4 @@ is_unloaded(What) -> end. check_f_calls(F1,F2) -> - {ok,[{{f,f1,0},F1},{{f,f2,0},F2}]} = cover:analyse(f,calls,function). + {ok,[{{f,f1,0},F1},{{f,f2,0},F2}|_]} = cover:analyse(f,calls,function). diff --git a/lib/tools/test/cover_SUITE_data/compile_beam/v.erl b/lib/tools/test/cover_SUITE_data/compile_beam/v.erl index 007957297a..7fb0b08d40 100644 --- a/lib/tools/test/cover_SUITE_data/compile_beam/v.erl +++ b/lib/tools/test/cover_SUITE_data/compile_beam/v.erl @@ -1,6 +1,9 @@ -module(v). - --export([f/0]). +-compile({ no_auto_import, [is_integer/1] }). +-export([f/0,f/1]). f() -> ok. + +f(Number) when erlang:is_integer(Number) -> + Number. diff --git a/lib/tools/test/cover_SUITE_data/compile_beam/z.erl b/lib/tools/test/cover_SUITE_data/compile_beam/z.erl new file mode 100644 index 0000000000..7a2b143dde --- /dev/null +++ b/lib/tools/test/cover_SUITE_data/compile_beam/z.erl @@ -0,0 +1 @@ +-module(z). diff --git a/lib/tools/test/cover_SUITE_data/f.erl b/lib/tools/test/cover_SUITE_data/f.erl index 1ef8bbdb49..ce2963014a 100644 --- a/lib/tools/test/cover_SUITE_data/f.erl +++ b/lib/tools/test/cover_SUITE_data/f.erl @@ -1,5 +1,5 @@ -module(f). --export([f1/0,f2/0]). +-export([f1/0,f2/0,call_f2_when_isolated/0]). f1() -> f1_line1, @@ -8,3 +8,12 @@ f1() -> f2() -> f2_line1, f2_line2. + +call_f2_when_isolated() -> + case nodes() of + [] -> + f2(); + _ -> + timer:sleep(100), + call_f2_when_isolated() + end. diff --git a/lib/tools/test/cprof_SUITE.erl b/lib/tools/test/cprof_SUITE.erl index ce5cf66a14..fa4068dade 100644 --- a/lib/tools/test/cprof_SUITE.erl +++ b/lib/tools/test/cprof_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2011. All Rights Reserved. +%% Copyright Ericsson AB 2002-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/tools/test/emacs_SUITE.erl b/lib/tools/test/emacs_SUITE.erl new file mode 100644 index 0000000000..657a3002a3 --- /dev/null +++ b/lib/tools/test/emacs_SUITE.erl @@ -0,0 +1,76 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(emacs_SUITE). + +%%-define(line_trace, 1). + +-export([all/0, init_per_testcase/2, end_per_testcase/2]). + +-export([bif_highlight/1]). + +all() -> + [bif_highlight]. + +init_per_testcase(_Case, Config) -> + ErlangEl = filename:join([code:lib_dir(tools),"emacs","erlang.el"]), + case file:read_file_info(ErlangEl) of + {ok, _} -> + [{el, ErlangEl}|Config]; + _ -> + {skip, "Could not find erlang.el"} + end. + +end_per_testcase(_Case, _Config) -> + ok. + +bif_highlight(Config) -> + ErlangEl = proplists:get_value(el,Config), + {ok, Bin} = file:read_file(ErlangEl), + + %% All auto-imported bifs + IntBifs = lists:usort( + [F || {F,A} <- erlang:module_info(exports), + erl_internal:bif(F,A)]), + + %% all bif which need erlang: prefix and are not operands + ExtBifs = lists:usort( + [F || {F,A} <- erlang:module_info(exports), + not erl_internal:bif(F,A) andalso + not is_atom(catch erl_internal:op_type(F,A))]), + + check_bif_highlight(Bin, <<"erlang-int-bifs">>, IntBifs), + check_bif_highlight(Bin, <<"erlang-ext-bifs">>, ExtBifs). + + +check_bif_highlight(Bin, Tag, Compare) -> + [_H,IntMatch,_T] = + re:split(Bin,<<"defvar ",Tag/binary, + "[^(]*\\(([^)]*)">>,[]), + EmacsIntBifs = [list_to_atom(S) || + S <- string:tokens(binary_to_list(IntMatch)," '\"\n")], + + ct:log("Emacs ~p",[EmacsIntBifs]), + ct:log("Int ~p",[Compare]), + + ct:log("Diff1 ~p",[Compare -- EmacsIntBifs]), + ct:log("Diff2 ~p",[EmacsIntBifs -- Compare]), + [] = Compare -- EmacsIntBifs, + [] = EmacsIntBifs -- Compare. + + diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl index fd3e111d8d..dc06678b8e 100644 --- a/lib/tools/test/xref_SUITE.erl +++ b/lib/tools/test/xref_SUITE.erl @@ -1,3 +1,4 @@ +%% -*- coding: utf-8 -*- %% %% %CopyrightBegin% %% @@ -46,7 +47,7 @@ -export([ add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1, replace/1, update/1, deprecated/1, trycatch/1, - abstract_modules/1, fun_mfa/1, fun_mfa_r14/1, + fun_mfa/1, fun_mfa_r14/1, fun_mfa_vars/1, qlc/1]). -export([ @@ -82,7 +83,7 @@ groups() -> modules]}, {files, [], [add, default, info, lib, read, read2, remove, replace, - update, deprecated, trycatch, abstract_modules, fun_mfa, + update, deprecated, trycatch, fun_mfa, fun_mfa_r14, fun_mfa_vars, qlc]}, {analyses, [], [analyze, basic, md, q, variables, unused_locals]}, @@ -1668,64 +1669,6 @@ trycatch(Conf) when is_list(Conf) -> ok. -abstract_modules(suite) -> []; -abstract_modules(doc) -> ["OTP-5520: Abstract (parameterized) modules."]; -abstract_modules(Conf) when is_list(Conf) -> - Dir = ?copydir, - File = fname(Dir, "absmod.erl"), - MFile = fname(Dir, "absmod"), - Beam = fname(Dir, "absmod.beam"), - Test = <<"-module(param, [A, B]). - - -export([args/1]). - - args(C) -> - X = local(C), - Y = THIS:new(), % undef - Z = new(A, B), - {X, Y, Z}. - - local(C) -> - module_info(C). - ">>, - - ?line ok = file:write_file(File, Test), - - %% The compiler will no longer allow us to have a mismatch between - %% the module name and the output file, so we must use a trick. - ?line {ok, param, BeamCode} = compile:file(File, [binary,debug_info]), - ?line ok = file:write_file(Beam, BeamCode), - - ?line {ok, _} = xref:start(s), - ?line {ok, param} = xref:add_module(s, MFile, {warnings,false}), - A = param, - ?line {ok, [{{{A,args,1},{'$M_EXPR',new,0}},[7]}, - {{{A,args,1},{A,local,1}},[6]}, - {{{A,args,1},{A,new,2}},[8]}, - {{{A,local,1},{A,module_info,1}},[12]}, - {{{param,new,2},{param,instance,2}},[0]}]} = - xref:q(s, "(Lin) E"), - ?line {ok,[{param,args,1}, - {param,instance,2}, - {param,local,1}, - {param,module_info,1}, - {param,new,2}]} = xref:q(s, "F"), - - ?line ok = check_state(s), - ?line xref:stop(s), - - ?line {ok, _} = xref:start(s, {xref_mode, modules}), - ?line {ok, param} = xref:add_module(s, MFile), - ?line {ok,[{param,args,1}, - {param,instance,2}, - {param,new,2}]} = xref:q(s, "X"), - ?line ok = check_state(s), - ?line xref:stop(s), - - ?line ok = file:delete(File), - ?line ok = file:delete(Beam), - ok. - fun_mfa(suite) -> []; fun_mfa(doc) -> ["OTP-5653: fun M:F/A."]; fun_mfa(Conf) when is_list(Conf) -> @@ -2521,7 +2464,7 @@ otp_10192(doc) -> otp_10192(Conf) when is_list(Conf) -> PrivDir = ?privdir, {ok, _Pid} = xref:start(s), - Dir = filename:join(PrivDir, "�"), + Dir = filename:join(PrivDir, "ä"), ok = file:make_dir(Dir), {ok, []} = xref:add_directory(s, Dir), xref:stop(s), |