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.erl130
1 files changed, 128 insertions, 2 deletions
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
index 8e4a1a4b1c..229d10ccee 100644
--- a/erts/test/otp_SUITE.erl
+++ b/erts/test/otp_SUITE.erl
@@ -24,7 +24,7 @@
-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,
- erl_file_encoding/1,xml_file_encoding/1]).
+ erl_file_encoding/1,xml_file_encoding/1,runtime_dependencies/1]).
-include_lib("test_server/include/test_server.hrl").
@@ -36,7 +36,8 @@ all() ->
[undefined_functions, deprecated_not_in_obsolete,
obsolete_but_not_deprecated, call_to_deprecated,
call_to_size_1, strong_components,
- erl_file_encoding, xml_file_encoding].
+ erl_file_encoding, xml_file_encoding,
+ runtime_dependencies].
groups() ->
[].
@@ -327,7 +328,9 @@ erl_file_encoding(_Config) ->
Wc = filename:join([Root,"**","*.erl"]),
ErlFiles = ordsets:subtract(ordsets:from_list(filelib:wildcard(Wc)),
release_files(Root, "*.erl")),
+ {ok, MP} = re:compile(".*lib/(ic)|(orber)|(cos).*", [unicode]),
Fs = [F || F <- ErlFiles,
+ filter_use_latin1_coding(F, MP),
case epp:read_encoding(F) of
none -> false;
_ -> true
@@ -341,6 +344,14 @@ erl_file_encoding(_Config) ->
?t:fail()
end.
+filter_use_latin1_coding(F, MP) ->
+ case re:run(F, MP) of
+ nomatch ->
+ true;
+ {match, _} ->
+ false
+ end.
+
xml_file_encoding(_Config) ->
XmlFiles = xml_files(),
Fs = [F || F <- XmlFiles, is_bad_encoding(F)],
@@ -380,6 +391,121 @@ is_bad_encoding(File) ->
true
end.
+runtime_dependencies(Config) ->
+ %% Ignore applications intentionally not declaring dependencies
+ %% found by xref.
+ IgnoreApps = [diameter],
+
+
+ %% Verify that (at least) OTP application runtime dependencies found
+ %% by xref are listed in the runtime_dependencies field of the .app file
+ %% of each application.
+ Server = ?config(xref_server, Config),
+ {ok, AE} = xref:q(Server, "AE"),
+ SAE = lists:keysort(1, AE),
+ put(ignored_failures, []),
+ {AppDep, AppDeps} = lists:foldl(fun ({App, App}, Acc) ->
+ Acc;
+ ({App, Dep}, {undefined, []}) ->
+ {{App, [Dep]}, []};
+ ({App, Dep}, {{App, Deps}, AppDeps}) ->
+ {{App, [Dep|Deps]}, AppDeps};
+ ({App, Dep}, {AppDep, AppDeps}) ->
+ {{App, [Dep]}, [AppDep | AppDeps]}
+ end,
+ {undefined, []},
+ SAE),
+ [] = lists:filter(fun ({missing_runtime_dependency,
+ AppFile,
+ common_test}) ->
+ %% The test_server app is contaminated by
+ %% common_test when run in a source tree. It
+ %% should however *not* be contaminated
+ %% when run in an installation.
+ case {filename:basename(AppFile),
+ is_run_in_src_tree()} of
+ {"test_server.app", true} ->
+ false;
+ _ ->
+ true
+ end;
+ (_) ->
+ true
+ end,
+ check_apps_deps([AppDep|AppDeps], IgnoreApps)),
+ case IgnoreApps of
+ [] ->
+ ok;
+ _ ->
+ Comment = lists:flatten(io_lib:format("Ignored applications: ~p "
+ "Ignored failures: ~p",
+ [IgnoreApps,
+ get(ignored_failures)])),
+ {comment, Comment}
+ end.
+
+is_run_in_src_tree() ->
+ %% At least currently run_erl is not present in <code-root>/bin
+ %% in the source tree, but present in <code-root>/bin of an
+ %% ordinary installation.
+ case file:read_file_info(filename:join([code:root_dir(),
+ "bin",
+ "run_erl"])) of
+ {ok, _} -> false;
+ {error, _} -> true
+ end.
+
+have_rdep(_App, [], _Dep) ->
+ false;
+have_rdep(App, [RDep | RDeps], Dep) ->
+ [AppStr, _VsnStr] = string:tokens(RDep, "-"),
+ case Dep == list_to_atom(AppStr) of
+ true ->
+ io:format("~p -> ~s~n", [App, RDep]),
+ true;
+ false ->
+ have_rdep(App, RDeps, Dep)
+ end.
+
+check_app_deps(_App, _AppFile, _AFDeps, [], _IgnoreApps) ->
+ [];
+check_app_deps(App, AppFile, AFDeps, [XRDep | XRDeps], IgnoreApps) ->
+ ResOtherDeps = check_app_deps(App, AppFile, AFDeps, XRDeps, IgnoreApps),
+ case have_rdep(App, AFDeps, XRDep) of
+ true ->
+ ResOtherDeps;
+ false ->
+ Failure = {missing_runtime_dependency, AppFile, XRDep},
+ case lists:member(App, IgnoreApps) of
+ true ->
+ put(ignored_failures, [Failure | get(ignored_failures)]),
+ ResOtherDeps;
+ false ->
+ [Failure | ResOtherDeps]
+ end
+ end.
+
+check_apps_deps([], _IgnoreApps) ->
+ [];
+check_apps_deps([{App, Deps}|AppDeps], IgnoreApps) ->
+ ResOtherApps = check_apps_deps(AppDeps, IgnoreApps),
+ AppFile = code:where_is_file(atom_to_list(App) ++ ".app"),
+ {ok,[{application, App, Info}]} = file:consult(AppFile),
+ case lists:keyfind(runtime_dependencies, 1, Info) of
+ {runtime_dependencies, RDeps} ->
+ check_app_deps(App, AppFile, RDeps, Deps, IgnoreApps)
+ ++ ResOtherApps;
+ false ->
+ Failure = {missing_runtime_dependencies_key, AppFile},
+ case lists:member(App, IgnoreApps) of
+ true ->
+ put(ignored_failures, [Failure | get(ignored_failures)]),
+ ResOtherApps;
+ false ->
+ [Failure | ResOtherApps]
+ end
+ end.
+
%%%
%%% Common help functions.
%%%