aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/tools/src/cover.erl72
-rw-r--r--lib/tools/test/cover_SUITE.erl63
-rw-r--r--lib/tools/test/cover_SUITE_data/cc.erl95
3 files changed, 84 insertions, 146 deletions
diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl
index 1d7d112c06..69e0f59b68 100644
--- a/lib/tools/src/cover.erl
+++ b/lib/tools/src/cover.erl
@@ -1472,7 +1472,7 @@ do_compile_beam(Module,BeamFile0,State) ->
{ok,Module,BeamFile};
error ->
{error, BeamFile};
- {error,Reason} -> % no abstract code
+ {error,Reason} -> % no abstract code or no 'file' attribute
{error, {Reason, BeamFile}}
end;
{error,no_beam} ->
@@ -1535,32 +1535,11 @@ do_compile_beam1(Module,Beam,UserOptions) ->
{error,E};
{raw_abstract_v1,Code} ->
Forms0 = epp:interpret_file_attribute(Code),
- {Forms,Vars} = transform(Forms0, Module),
-
- %% We need to recover the source from the compilation
- %% info otherwise the newly compiled module will have
- %% source pointing to the current directory
- SourceInfo = get_source_info(Module, Beam),
-
- %% Compile and load the result
- %% It's necessary to check the result of loading since it may
- %% fail, for example if Module resides in a sticky directory
- {ok, Module, Binary} = compile:forms(Forms, SourceInfo ++ UserOptions),
- case code:load_binary(Module, ?TAG, Binary) of
- {module, Module} ->
-
- %% Store info about all function clauses in database
- InitInfo = lists:reverse(Vars#vars.init_info),
- ets:insert(?COVER_CLAUSE_TABLE, {Module, InitInfo}),
-
- %% Store binary code so it can be loaded on remote nodes
- ets:insert(?BINARY_TABLE, {Module, Binary}),
-
- {ok, Module};
-
- _Error ->
- do_clear(Module),
- error
+ case find_main_filename(Forms0) of
+ {ok,MainFile} ->
+ do_compile_beam2(Module,Beam,UserOptions,Forms0,MainFile);
+ Error ->
+ Error
end;
{_VSN,_Code} ->
%% Wrong version of abstract code. Just report that there
@@ -1577,6 +1556,35 @@ get_abstract_code(Module, Beam) ->
Error -> Error
end.
+do_compile_beam2(Module,Beam,UserOptions,Forms0,MainFile) ->
+ {Forms,Vars} = transform(Forms0, Module, MainFile),
+
+ %% We need to recover the source from the compilation
+ %% info otherwise the newly compiled module will have
+ %% source pointing to the current directory
+ SourceInfo = get_source_info(Module, Beam),
+
+ %% Compile and load the result
+ %% It's necessary to check the result of loading since it may
+ %% fail, for example if Module resides in a sticky directory
+ {ok, Module, Binary} = compile:forms(Forms, SourceInfo ++ UserOptions),
+ case code:load_binary(Module, ?TAG, Binary) of
+ {module, Module} ->
+
+ %% Store info about all function clauses in database
+ InitInfo = lists:reverse(Vars#vars.init_info),
+ ets:insert(?COVER_CLAUSE_TABLE, {Module, InitInfo}),
+
+ %% Store binary code so it can be loaded on remote nodes
+ ets:insert(?BINARY_TABLE, {Module, Binary}),
+
+ {ok, Module};
+
+ _Error ->
+ do_clear(Module),
+ error
+ end.
+
get_source_info(Module, Beam) ->
Compile = get_compile_info(Module, Beam),
case lists:keyfind(source, 1, Compile) of
@@ -1599,8 +1607,7 @@ get_compile_info(Module, Beam) ->
[]
end.
-transform(Code, Module) ->
- MainFile=find_main_filename(Code),
+transform(Code, Module, MainFile) ->
Vars0 = #vars{module=Module},
{ok,MungedForms,Vars} = transform_2(Code,[],Vars0,MainFile,on),
{MungedForms,Vars}.
@@ -1608,9 +1615,12 @@ transform(Code, Module) ->
%% Helpfunction which returns the first found file-attribute, which can
%% be interpreted as the name of the main erlang source file.
find_main_filename([{attribute,_,file,{MainFile,_}}|_]) ->
- MainFile;
+ {ok,MainFile};
find_main_filename([_|Rest]) ->
- find_main_filename(Rest).
+ find_main_filename(Rest);
+find_main_filename([]) ->
+ {error, no_file_attribute}.
+
transform_2([Form0|Forms],MungedForms,Vars,MainFile,Switch) ->
Form = expand(Form0),
diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl
index 25c9317608..483ea9774e 100644
--- a/lib/tools/test/cover_SUITE.erl
+++ b/lib/tools/test/cover_SUITE.erl
@@ -19,43 +19,16 @@
%%
-module(cover_SUITE).
--export([all/0, init_per_testcase/2, end_per_testcase/2,
- suite/0,groups/0,init_per_suite/1, end_per_suite/1,
- init_per_group/2,end_per_group/2]).
-
--export([coverage/1, coverage_analysis/1,
- start/1, compile/1, analyse/1, misc/1, stop/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,
- otp_10979_hanging_node/1, compile_beam_opts/1, eep37/1,
- analyse_no_beam/1, line_0/1]).
-
--export([do_coverage/1]).
-
--export([distribution_performance/1]).
+-compile(export_all).
-include_lib("test_server/include/test_server.hrl").
-%%----------------------------------------------------------------------
-%% The following directory structure is assumed:
-%% cwd __________________________________________
-%% | \ \ \ \ \ \ \
-%% a b cc d f d1 compile_beam_____ otp_6115
-%% | \ \ \ \ \ \ \
-%% e crypt v w x d f1 f2
-%% |
-%% y
-%%----------------------------------------------------------------------
-
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
NoStartStop = [eif,otp_5305,otp_5418,otp_7095,otp_8273,
otp_8340,otp_8188,compile_beam_opts,eep37,
- analyse_no_beam, line_0],
+ analyse_no_beam, line_0, compile_beam_no_file],
StartStop = [start, compile, analyse, misc, stop,
distribution, reconnect, die_and_reconnect,
dont_reconnect_after_stop, stop_node_after_disconnect,
@@ -778,8 +751,8 @@ distribution_performance(Config) ->
%% [{ok,_} = cover:compile_beam(Mod) || Mod <- Mods]
%% end,
CFun = fun() -> cover:compile_beam(Mods) end,
- {CT,CA} = timer:tc(CFun),
-% erlang:display(CA),
+ {CT,_CA} = timer:tc(CFun),
+% erlang:display(_CA),
erlang:display({compile,CT}),
{SNT,_} = timer:tc(fun() -> {ok,[N1]} = cover:start(nodes()) end),
@@ -799,7 +772,7 @@ distribution_performance(Config) ->
% Fun = fun() -> cover:reset() end,
- {AT,A} = timer:tc(Fun),
+ {AT,_A} = timer:tc(Fun),
erlang:display({analyse,AT}),
% erlang:display(lists:sort([X || X={_MFA,N} <- lists:append([L || {ok,L}<-A]), N=/=0])),
@@ -1746,6 +1719,32 @@ line_0(Config) ->
ok.
+%% OTP-13200: Return error instead of crashing when trying to compile
+%% a beam which has no 'file' attribute.
+compile_beam_no_file(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ Dir = filename:join(PrivDir,"compile_beam_no_file"),
+ ok = filelib:ensure_dir(filename:join(Dir,"*")),
+ code:add_patha(Dir),
+ Str = lists:concat(
+ ["-module(nofile).\n"
+ "-compile(export_all).\n"
+ "foo() -> ok.\n"]),
+ TT = do_scan(Str),
+ Forms = [ begin {ok,Y} = erl_parse:parse_form(X),Y end || X <- TT ],
+ {ok,_,Bin} = compile:forms(Forms,[debug_info]),
+ BeamFile = filename:join(Dir,"nofile.beam"),
+ ok = file:write_file(BeamFile,Bin),
+ {error,{no_file_attribute,BeamFile}} = cover:compile_beam(nofile),
+ [{error,{no_file_attribute,BeamFile}}] = cover:compile_beam_directory(Dir),
+ ok.
+
+do_scan([]) ->
+ [];
+do_scan(Str) ->
+ {done,{ok,T,_},C} = erl_scan:tokens([],Str,0),
+ [ T | do_scan(C) ].
+
%%--Auxiliary------------------------------------------------------------
diff --git a/lib/tools/test/cover_SUITE_data/cc.erl b/lib/tools/test/cover_SUITE_data/cc.erl
index 587bdbe493..7eb165ef8a 100644
--- a/lib/tools/test/cover_SUITE_data/cc.erl
+++ b/lib/tools/test/cover_SUITE_data/cc.erl
@@ -1,88 +1,17 @@
-module(cc).
--export([epp/1, epp/2, dbg/1, dbg/2, cvr/1, cvr/2]).
--export([p/2, pp/2]).
+-compile(export_all).
-%% epp(Module) - Creates Module.epp which contains all forms of Module
-%% as obtained by using epp.
-%%
-%% dbg(Module) - Creates Module.dbg which contains all forms of Module
-%% as obtained by using beam_lib:chunks/2.
-%%
-%% cvr(Module) - Creates Module.cvr which contains all forms of Module
-%% as obtained by using cover:transform/3.
-%%
+%% This is a dummy module used only for cover compiling. The content
+%% of this module has no meaning for the test.
-epp(Module) ->
- epp(Module, p).
-epp(Module, P) ->
- File = atom_to_list(Module)++".erl",
- {ok,Cwd} = file:get_cwd(),
- {ok, Fd1} = epp:open(File, [Cwd], []),
- {ok, Fd2} = file:open(atom_to_list(Module)++".epp", write),
+foo() ->
+ T = erlang:time(),
+ spawn(fun() -> bar(T) end).
- epp(Fd1, Fd2, P),
-
- epp:close(Fd1),
- file:close(Fd2),
- ok.
-
-epp(Fd1, Fd2, P) ->
- case epp:parse_erl_form(Fd1) of
- {ok, {attribute,Line,Attr,Data}} ->
- epp(Fd1, Fd2, P);
- {ok, Form} when P==p ->
- io:format(Fd2, "~p.~n", [Form]),
- epp(Fd1, Fd2, P);
- {ok, Form} when P==pp ->
- io:format(Fd2, "~p.~n", [erl_pp:form(Form)]),
- epp(Fd1, Fd2, P);
- {eof, Line} ->
- ok
- end.
-
-cvr(Module) ->
- cvr(Module, p).
-cvr(Module, P) ->
- case beam_lib:chunks(Module, [abstract_code]) of
- {ok, {Module, [{abstract_code, no_abstract_code}]}} ->
- {error, {no_debug_info,Module}};
- {ok, {Module, [{abstract_code, {Vsn, Forms}}]}} ->
- Vars = {vars,Module,Vsn, [],
- undefined, undefined, undefined, undefined, undefined,
- undefined,
- false},
- {ok, TForms, _Vars2} = cover:transform(Forms, [], Vars),
- File = atom_to_list(Module)++".cvr",
- apply(?MODULE, P, [File, TForms]);
- Error ->
- Error
+bar(T) ->
+ receive
+ X ->
+ T1 = erlang:time(),
+ io:format("received ~p at ~p. Last time: ~p~n",[X,T1,T]),
+ bar(T1)
end.
-
-dbg(Module) ->
- dbg(Module, p).
-dbg(Module, P) ->
- case beam_lib:chunks(Module, [abstract_code]) of
- {ok, {Module, [{abstract_code, no_abstract_code}]}} ->
- {error, {no_debug_info,Module}};
- {ok, {Module, [{abstract_code, {Vsn, Forms}}]}} ->
- File = atom_to_list(Module)++".dbg",
- apply(?MODULE, P, [File, Forms]);
- Error ->
- Error
- end.
-
-p(File, Forms) ->
- {ok, Fd} = file:open(File, write),
- lists:foreach(fun(Form) ->
- io:format(Fd, "~p.~n", [Form])
- end,
- Forms),
- file:close(Fd).
-
-pp(File, Forms) ->
- {ok, Fd} = file:open(File, write),
- lists:foreach(fun(Form) ->
- io:format(Fd, "~s", [erl_pp:form(Form)])
- end,
- Forms),
- file:close(Fd).