aboutsummaryrefslogtreecommitdiffstats
path: root/erts/test/otp_SUITE.erl
diff options
context:
space:
mode:
Diffstat (limited to 'erts/test/otp_SUITE.erl')
-rw-r--r--erts/test/otp_SUITE.erl297
1 files changed, 297 insertions, 0 deletions
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
new file mode 100644
index 0000000000..c6769743dd
--- /dev/null
+++ b/erts/test/otp_SUITE.erl
@@ -0,0 +1,297 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-2009. 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(otp_SUITE).
+
+-export([all/1,init_per_suite/1,end_per_suite/1]).
+-export([undefined_functions/1,deprecated_not_in_obsolete/1,
+ obsolete_but_not_deprecated/1,call_to_deprecated/1,
+ call_to_size_1/1,strong_components/1]).
+
+-include("test_server.hrl").
+-import(lists, [filter/2,foldl/3,foreach/2]).
+
+all(suite) ->
+ [undefined_functions,deprecated_not_in_obsolete,
+ obsolete_but_not_deprecated,call_to_deprecated,
+ call_to_size_1,strong_components].
+
+init_per_suite(Config) ->
+ Dog = test_server:timetrap(?t:minutes(10)),
+ Root = code:root_dir(),
+ Server = daily_xref,
+ ?line xref:start(Server),
+ ?line xref:set_default(Server, [{verbose,false},
+ {warnings,false},
+ {builtins,true}]),
+ ?line {ok,_Relname} = xref:add_release(Server, Root, {name,otp}),
+
+ %% If we are running the tests in the source tree, the ERTS application
+ %% is not in the code path. We must add it explicitly.
+ case code:lib_dir(erts) of
+ {error,bad_name} ->
+ Erts = filename:join([code:root_dir(),"erts","preloaded","ebin"]),
+ ?line {ok,_} = xref:add_directory(Server, Erts, []);
+ _ ->
+ ok
+ end,
+
+ ?line ?t:timetrap_cancel(Dog),
+ [{xref_server,Server}|Config].
+
+end_per_suite(Config) ->
+ Server = ?config(xref_server, Config),
+ catch xref:stop(Server),
+ Config.
+
+undefined_functions(Config) when is_list(Config) ->
+ Server = ?config(xref_server, Config),
+
+ %% Exclude calls from generated modules in the SSL application.
+ ExcludeFrom = "SSL-PKIX|PKIX.*|ssl_pkix_oid",
+ ?line UndefS = xref_base:analysis(undefined_function_calls),
+ ?line Q = io_lib:format("Undef = ~s,"
+ "ExcludedFrom = ~p:_/_,"
+ "Undef - Undef | ExcludedFrom",
+ [UndefS,ExcludeFrom]),
+ ?line {ok,Undef0} = xref:q(Server, lists:flatten(Q)),
+ ?line Undef1 = hipe_filter(Undef0),
+ ?line Undef2 = ssl_crypto_filter(Undef1),
+ ?line Undef3 = edoc_filter(Undef2),
+ ?line Undef = eunit_filter(Undef3),
+ ?line Undef = megaco_filter(Undef),
+
+ case Undef of
+ [] -> ok;
+ _ ->
+ foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls undefined ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, Undef),
+ ?line ?t:fail({length(Undef),undefined_functions_in_otp})
+
+ end,
+
+ ok.
+
+hipe_filter(Undef) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined ->
+ filter(fun ({_,{hipe_bifs,_,_}}) -> false;
+ ({_,{hipe,_,_}}) -> false;
+ ({_,{hipe_consttab,_,_}}) -> false;
+ ({_,{hipe_converters,_,_}}) -> false;
+ ({{code,_,_},{Mod,_,_}}) ->
+ not is_hipe_module(Mod);
+ ({{code_server,_,_},{Mod,_,_}}) ->
+ not is_hipe_module(Mod);
+ ({{compile,_,_},{Mod,_,_}}) ->
+ not is_hipe_module(Mod);
+ ({{hipe,_,_},{Mod,_,_}}) ->
+ %% See comment for the next clause.
+ not is_hipe_module(Mod);
+ ({{cerl_to_icode,translate_flags1,2},
+ {hipe_rtl_arch,endianess,0}}) ->
+ false;
+ ({{Caller,_,_},{Callee,_,_}}) ->
+ %% Part of the hipe application is here
+ %% for the sake of Dialyzer. There are many
+ %% undefined calls within the hipe application.
+ not is_hipe_module(Caller) orelse
+ not is_hipe_module(Callee);
+ (_) -> true
+ end, Undef);
+ _Arch ->
+ filter(fun ({{Mod,_,_},{hipe_bifs,write_u64,2}}) ->
+ %% Unavailable except in 64 bit AMD. Ignore it.
+ not is_hipe_module(Mod);
+ (_) -> true
+ end, Undef)
+ end.
+
+is_hipe_module(Mod) ->
+ case atom_to_list(Mod) of
+ "hipe_"++_ -> true;
+ _ -> false
+ end.
+
+ssl_crypto_filter(Undef) ->
+ case {code:lib_dir(crypto),code:lib_dir(ssl)} of
+ {{error,bad_name},{error,bad_name}} ->
+ filter(fun({_,{ssl,_,_}}) -> false;
+ ({_,{crypto,_,_}}) -> false;
+ (_) -> true
+ end, Undef);
+ {_,_} -> Undef
+ end.
+
+edoc_filter(Undef) ->
+ %% Filter away function call that is catched.
+ filter(fun({{edoc_lib,uri_get_http,1},{http,request_sync,2}}) -> false;
+ (_) -> true
+ end, Undef).
+
+eunit_filter(Undef) ->
+ filter(fun({{eunit_test,wrapper_test_exported_,0},
+ {eunit_test,nonexisting_function,0}}) -> false;
+ (_) -> true
+ end, Undef).
+
+megaco_filter(Undef) ->
+ %% Intentional calls to undefined functions.
+ filter(fun({{megaco_compact_text_encoder,encode_action_reply,3},
+ {megaco_compact_text_encoder_v3,encode_action_reply,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_action_request,3},
+ {megaco_compact_text_encoder_v3,encode_action_request,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_action_requests,3},
+ {megaco_compact_text_encoder_v3,encode_action_requests,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_command_request,3},
+ {megaco_compact_text_encoder_v3,encode_command_request,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_message,3},
+ {megaco_compact_text_encoder_v3,encode_message,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_transaction,3},
+ {megaco_compact_text_encoder_v3,encode_transaction,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_action_reply,3},
+ {megaco_pretty_text_encoder_v3,encode_action_reply,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_action_request,3},
+ {megaco_pretty_text_encoder_v3,encode_action_request,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_action_requests,3},
+ {megaco_pretty_text_encoder_v3,encode_action_requests,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_command_request,3},
+ {megaco_pretty_text_encoder_v3,encode_command_request,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_message,3},
+ {megaco_pretty_text_encoder_v3,encode_message,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_transaction,3},
+ {megaco_pretty_text_encoder_v3,encode_transaction,2}}) -> false;
+ (_) -> true
+ end, Undef).
+
+deprecated_not_in_obsolete(Config) when is_list(Config) ->
+ ?line Server = ?config(xref_server, Config),
+ ?line {ok,DeprecatedFunctions} = xref:q(Server, "DF"),
+
+ ?line L = foldl(fun({M,F,A}=MFA, Acc) ->
+ case otp_internal:obsolete(M, F, A) of
+ no -> [MFA|Acc];
+ _ -> Acc
+ end
+ end, [], DeprecatedFunctions),
+ case L of
+ [] -> ok;
+ _ ->
+ io:put_chars("The following functions have -deprecated() attributes,\n"
+ "but are not listed in otp_internal:obsolete/3.\n"),
+ ?line print_mfas(L),
+ ?line ?t:fail({length(L),deprecated_but_not_obsolete})
+ end.
+
+obsolete_but_not_deprecated(Config) when is_list(Config) ->
+ ?line Server = ?config(xref_server, Config),
+ ?line {ok,NotDeprecated} = xref:q(Server, "X - DF"),
+
+ ?line L = foldl(fun({M,F,A}=MFA, Acc) ->
+ case otp_internal:obsolete(M, F, A) of
+ no -> Acc;
+ _ -> [MFA|Acc]
+ end
+ end, [], NotDeprecated),
+
+ case L of
+ [] -> ok;
+ _ ->
+ io:put_chars("The following functions are listed "
+ "in otp_internal:obsolete/3,\n"
+ "but don't have -deprecated() attributes.\n"),
+ ?line print_mfas(L),
+ ?line ?t:fail({length(L),obsolete_but_not_deprecated})
+ end.
+
+
+call_to_deprecated(Config) when is_list(Config) ->
+ Server = ?config(xref_server, Config),
+ ?line {ok,DeprecatedCalls} = xref:q(Server, "strict(E || DF)"),
+ foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls deprecated ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, DeprecatedCalls),
+ {comment,integer_to_list(length(DeprecatedCalls))++" calls to deprecated functions"}.
+
+call_to_size_1(Config) when is_list(Config) ->
+ Server = ?config(xref_server, Config),
+
+ %% Applications that do not call erlang:size/1:
+ Apps = [compiler,debugger,kernel,observer,parsetools,
+ runtime_tools,stdlib,tools,webtool],
+
+ Fs = [{erlang,size,1}],
+
+ Q1 = io_lib:format("E || ~p : Fun", [Fs]),
+ ?line {ok,AllCallsToSize1} = xref:q(Server, lists:flatten(Q1)),
+
+ Q2 = io_lib:format("E | ~p : App || ~p : Fun", [Apps,Fs]),
+ ?line {ok,CallsToSize1} = xref:q(Server, lists:flatten(Q2)),
+
+ case CallsToSize1 of
+ [] ->
+ ok;
+ _ ->
+ io:format("These calls cause an error:~n"),
+ foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls soon to be deprecated ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, CallsToSize1)
+ end,
+
+ %% Enumerate calls to erlang:size/1 from other applications than
+ %% the ones known not to call erlang:size/1:
+ case AllCallsToSize1--CallsToSize1 of
+ [] ->
+ ok;
+ Calls ->
+ io:format("~n~nThese calls do not cause an error (yet):~n"),
+ foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls soon to be deprecated ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, Calls)
+ end,
+ case CallsToSize1 of
+ [] ->
+ ok;
+ _ ->
+ ?line ?t:fail({length(CallsToSize1),calls_to_size_1})
+ end.
+
+strong_components(Config) when is_list(Config) ->
+ Server = ?config(xref_server, Config),
+ ?line {ok,Cs} = xref:q(Server, "components AE"),
+ io:format("\n\nStrong components:\n\n~p\n", [Cs]),
+ ok.
+
+%%%
+%%% Common help functions.
+%%%
+
+
+print_mfas([MFA|T]) ->
+ io:format("~s\n", [format_mfa(MFA)]),
+ print_mfas(T);
+print_mfas([]) -> ok.
+
+format_mfa({M,F,A}) ->
+ lists:flatten(io_lib:format("~s:~s/~p", [M,F,A])).