summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/rebar_as_SUITE.erl2
-rw-r--r--test/rebar_compile_SUITE.erl46
-rw-r--r--test/rebar_ct_SUITE.erl63
-rw-r--r--test/rebar_deps_SUITE.erl30
-rw-r--r--test/rebar_eunit_SUITE.erl5
-rw-r--r--test/rebar_hooks_SUITE.erl18
-rw-r--r--test/rebar_pkg_SUITE.erl2
-rw-r--r--test/rebar_profiles_SUITE.erl25
-rw-r--r--test/rebar_release_SUITE.erl25
-rw-r--r--test/rebar_src_dirs_SUITE.erl98
-rw-r--r--test/rebar_test_utils.erl12
-rw-r--r--test/rebar_upgrade_SUITE.erl93
-rw-r--r--test/rebar_xref_SUITE.erl59
-rw-r--r--test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/rebar.config12
-rw-r--r--test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1.app.src16
-rw-r--r--test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_app.erl26
-rw-r--r--test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_sup.erl35
-rw-r--r--test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2.app.src17
-rw-r--r--test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_app.erl26
-rw-r--r--test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_sup.erl35
20 files changed, 601 insertions, 44 deletions
diff --git a/test/rebar_as_SUITE.erl b/test/rebar_as_SUITE.erl
index ce8046b..78ea8ae 100644
--- a/test/rebar_as_SUITE.erl
+++ b/test/rebar_as_SUITE.erl
@@ -176,7 +176,7 @@ error_on_empty_tasks(Config) ->
warn_match(App, History) ->
lists:any(
- fun({_, {rebar_log,log, [warn, "No entry for profile ~s in config.",
+ fun({_, {rebar_log,log, [warn, "No entry for profile ~ts in config.",
[ArgApp]]}, _}) -> ArgApp =:= App
; (_) ->
false
diff --git a/test/rebar_compile_SUITE.erl b/test/rebar_compile_SUITE.erl
index 9f01496..5a18745 100644
--- a/test/rebar_compile_SUITE.erl
+++ b/test/rebar_compile_SUITE.erl
@@ -78,21 +78,10 @@ all() ->
recompile_when_parse_transform_as_opt_changes,
recompile_when_parse_transform_inline_changes,
regex_filter_skip, regex_filter_regression,
- %% recompile behaviour when `ERL_COMPILER_OPTIONS` differs prior to 19.x
- recursive, no_recursive] ++ recompile_when_env_changes_test().
-
-recompile_when_env_changes_test() ->
- _ = code:ensure_loaded(os),
- UnSetEnv = erlang:function_exported(os, unsetenv, 1),
- _ = code:ensure_loaded(compile),
- EnvOpts = erlang:function_exported(compile, env_compiler_options, 0),
- case {UnSetEnv, EnvOpts} of
- {true, true} ->
- [dont_recompile_when_erl_compiler_options_env_does_not_change,
- recompile_when_erl_compiler_options_env_changes];
- {true, false} -> [always_recompile_when_erl_compiler_options_set];
- {false, _} -> []
- end.
+ recursive, no_recursive,
+ always_recompile_when_erl_compiler_options_set,
+ dont_recompile_when_erl_compiler_options_env_does_not_change,
+ recompile_when_erl_compiler_options_env_changes].
groups() ->
[{basic_app, [], [build_basic_app, paths_basic_app, clean_basic_app]},
@@ -266,7 +255,31 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
ok.
-init_per_testcase(_, Config) ->
+init_per_testcase(Test, Config) when
+ Test == dont_recompile_when_erl_compiler_options_env_does_not_change
+ orelse
+ Test == recompile_when_erl_compiler_options_env_changes ->
+ _ = code:ensure_loaded(os),
+ UnSetEnv = erlang:function_exported(os, unsetenv, 1),
+ _ = code:ensure_loaded(compile),
+ EnvOpts = erlang:function_exported(compile, env_compiler_options, 0),
+ case {UnSetEnv, EnvOpts} of
+ {true, true} -> maybe_init_config(Config);
+ _ -> {skip, "compile:env_compiler_options/0 unavailable"}
+ end;
+init_per_testcase(always_recompile_when_erl_compiler_options_set, Config) ->
+ _ = code:ensure_loaded(os),
+ UnSetEnv = erlang:function_exported(os, unsetenv, 1),
+ _ = code:ensure_loaded(compile),
+ EnvOpts = erlang:function_exported(compile, env_compiler_options, 0),
+ case {UnSetEnv, EnvOpts} of
+ {true, true} -> {skip, "compile:env_compiler_options/0 available"};
+ {true, false} -> maybe_init_config(Config);
+ _ -> {skip, "os:unsetenv/1 unavailable"}
+ end;
+init_per_testcase(_, Config) -> maybe_init_config(Config).
+
+maybe_init_config(Config) ->
case ?config(apps, Config) of
undefined -> rebar_test_utils:init_rebar_state(Config);
_ -> Config
@@ -276,7 +289,6 @@ end_per_testcase(_, _Config) ->
catch meck:unload().
-
%% test cases
build_basic_app(Config) ->
diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl
index 06dc76e..70cf60c 100644
--- a/test/rebar_ct_SUITE.erl
+++ b/test/rebar_ct_SUITE.erl
@@ -55,7 +55,9 @@
testspec/1,
testspec_at_root/1,
testspec_parse_error/1,
- cmd_vs_cfg_opts/1]).
+ cmd_vs_cfg_opts/1,
+ single_testspec_in_ct_opts/1,
+ compile_only/1]).
-include_lib("eunit/include/eunit.hrl").
-include_lib("common_test/include/ct.hrl").
@@ -75,7 +77,9 @@ all() -> [{group, basic_app},
testspec,
testspec_at_root,
testspec_parse_error,
- cmd_vs_cfg_opts].
+ cmd_vs_cfg_opts,
+ single_testspec_in_ct_opts,
+ compile_only].
groups() -> [{basic_app, [], [basic_app_default_dirs,
basic_app_default_beams,
@@ -1548,6 +1552,57 @@ cmd_vs_cfg_opts(Config) ->
ok.
+single_testspec_in_ct_opts(Config) ->
+ C = rebar_test_utils:init_rebar_state(Config, "ct_testspec_"),
+
+ AppDir = ?config(apps, C),
+
+ Name = rebar_test_utils:create_random_name("ct_testspec_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+ Spec = filename:join([AppDir, "test", "some.spec"]),
+ ok = filelib:ensure_dir(Spec),
+ ok = file:write_file(Spec, "{suites,\".\",all}.\n"),
+
+ {ok,Wd} = file:get_cwd(),
+ ok = file:set_cwd(AppDir),
+
+ RebarConfig = [{ct_opts, [{spec,"test/some.spec"}]}],
+
+ {ok, State} = rebar_test_utils:run_and_check(C, RebarConfig, ["as", "test", "lock"], return),
+
+ Providers = rebar_state:providers(State),
+ Namespace = rebar_state:namespace(State),
+ CommandProvider = providers:get_provider(ct, Providers, Namespace),
+ GetOptSpec = providers:opts(CommandProvider),
+
+ %% Testspec in "test" directory
+ {ok, GetOptResult1} = getopt:parse(GetOptSpec, []),
+ State1 = rebar_state:command_parsed_args(State, GetOptResult1),
+ Tests1 = rebar_prv_common_test:prepare_tests(State1),
+ {ok, T1} = Tests1,
+ "test/some.spec" = proplists:get_value(spec,T1),
+ {ok, _NewState} = rebar_prv_common_test:compile(State1, Tests1),
+
+ ok = file:set_cwd(Wd),
+ ok.
+
+compile_only(Config) ->
+ C = rebar_test_utils:init_rebar_state(Config, "compile_only_"),
+
+ AppDir = ?config(apps, C),
+
+ Name = rebar_test_utils:create_random_name(atom_to_list(basic_app) ++ "_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ Suite = filename:join([AppDir, "test", Name ++ "_SUITE.erl"]),
+ ok = filelib:ensure_dir(Suite),
+ ok = file:write_file(Suite, test_suite(Name)),
+
+ {ok, _State} = rebar_test_utils:run_and_check(C, [], ["ct", "--compile_only"], {ok, [{app,Name}], "test"}).
+
+
%% helper for generating test data
test_suite(Name) ->
io_lib:format("-module(~ts_SUITE).\n"
@@ -1556,7 +1611,7 @@ test_suite(Name) ->
"some_test(_) -> ok.\n", [Name]).
cmd_sys_config_file(AppName) ->
- io_lib:format("[{~s, [{key, cmd_value}]}].", [AppName]).
+ io_lib:format("[{~ts, [{key, cmd_value}]}].", [AppName]).
cfg_sys_config_file(AppName) ->
- io_lib:format("[{~s, [{key, cfg_value}]}].", [AppName]).
+ io_lib:format("[{~ts, [{key, cfg_value}]}].", [AppName]).
diff --git a/test/rebar_deps_SUITE.erl b/test/rebar_deps_SUITE.erl
index 6b2ecea..ae50ea3 100644
--- a/test/rebar_deps_SUITE.erl
+++ b/test/rebar_deps_SUITE.erl
@@ -7,7 +7,7 @@ all() -> [sub_app_deps, newly_added_dep, newly_added_after_empty_lock,
http_proxy_settings, https_proxy_settings,
http_os_proxy_settings, https_os_proxy_settings,
semver_matching_lt, semver_matching_lte, semver_matching_gt,
- valid_version, {group, git}, {group, pkg}].
+ valid_version, top_override, {group, git}, {group, pkg}].
groups() ->
[{all, [], [flat, pick_highest_left, pick_highest_right,
@@ -47,6 +47,8 @@ init_per_testcase(newly_added_dep, Config) ->
rebar_test_utils:init_rebar_state(Config);
init_per_testcase(sub_app_deps, Config) ->
rebar_test_utils:init_rebar_state(Config);
+init_per_testcase(top_override, Config) ->
+ rebar_test_utils:init_rebar_state(Config);
init_per_testcase(http_proxy_settings, Config) ->
%% Create private rebar.config
Priv = ?config(priv_dir, Config),
@@ -255,6 +257,32 @@ circular1(Config) -> run(Config).
circular2(Config) -> run(Config).
circular_skip(Config) -> run(Config).
+%% Test that a top-level application overtakes dependencies, and
+%% works even if said deps do not exist.
+top_override(Config) ->
+ AppDir = ?config(apps, Config),
+ ct:pal("dir: ~p", [AppDir]),
+ Name1 = rebar_test_utils:create_random_name("sub_app1_"),
+ Name2 = rebar_test_utils:create_random_name("sub_app2_"),
+ SubAppsDir1 = filename:join([AppDir, "apps", Name1]),
+ SubAppsDir2 = filename:join([AppDir, "apps", Name2]),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(SubAppsDir1, Name1, Vsn, [kernel, stdlib]),
+ rebar_test_utils:create_app(SubAppsDir2, Name2, Vsn, [kernel, stdlib]),
+ rebar_test_utils:create_config(
+ SubAppsDir1,
+ [{deps, [list_to_atom(Name2)]}]
+ ),
+ rebar_test_utils:create_config(
+ SubAppsDir2,
+ [{deps, [{list_to_atom(Name1),
+ {git, "https://example.org", {branch, "master"}}}]}]
+ ),
+ rebar_test_utils:run_and_check(
+ Config, [], ["compile"],
+ {ok, [{app, Name1}, {app,Name2}]}
+ ).
+
%% Test that the deps of project apps that have their own rebar.config
%% are included, but that top level rebar.config deps take precedence
sub_app_deps(Config) ->
diff --git a/test/rebar_eunit_SUITE.erl b/test/rebar_eunit_SUITE.erl
index 6fb325b..4805b3d 100644
--- a/test/rebar_eunit_SUITE.erl
+++ b/test/rebar_eunit_SUITE.erl
@@ -1,7 +1,8 @@
-module(rebar_eunit_SUITE).
-export([all/0, groups/0]).
--export([init_per_suite/1, init_per_group/2, end_per_group/2]).
+-export([init_per_suite/1, end_per_suite/1]).
+-export([init_per_group/2, end_per_group/2]).
-export([basic_app_compiles/1, basic_app_files/1]).
-export([basic_app_exports/1, basic_app_testset/1]).
-export([basic_app_eunit_macro/1]).
@@ -60,6 +61,8 @@ init_per_suite(Config) ->
{ok, _} = zip:extract(filename:join([PrivDir, "multi_app.zip"]), [{cwd, PrivDir}]),
Config.
+end_per_suite(Config) -> Config.
+
init_per_group(basic_app, Config) ->
GroupState = rebar_test_utils:init_rebar_state(Config, "basic_app_"),
diff --git a/test/rebar_hooks_SUITE.erl b/test/rebar_hooks_SUITE.erl
index b121dd5..f7fcb82 100644
--- a/test/rebar_hooks_SUITE.erl
+++ b/test/rebar_hooks_SUITE.erl
@@ -9,6 +9,7 @@
build_and_clean_app/1,
escriptize_artifacts/1,
run_hooks_once/1,
+ run_hooks_once_profiles/1,
run_hooks_for_plugins/1,
eunit_app_hooks/1,
deps_hook_namespace/1]).
@@ -33,8 +34,9 @@ end_per_testcase(_, _Config) ->
catch meck:unload().
all() ->
- [build_and_clean_app, run_hooks_once, escriptize_artifacts,
- run_hooks_for_plugins, deps_hook_namespace, eunit_app_hooks].
+ [build_and_clean_app, run_hooks_once, run_hooks_once_profiles,
+ escriptize_artifacts, run_hooks_for_plugins, deps_hook_namespace,
+ eunit_app_hooks].
%% Test post provider hook cleans compiled project app, leaving it invalid
build_and_clean_app(Config) ->
@@ -98,6 +100,18 @@ run_hooks_once(Config) ->
rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, [{app, Name, valid}]}).
+%% test that even if a hook is defined at the project level in a used profile
+%% the hook is not run for each application in the project umbrella
+run_hooks_once_profiles(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("app1_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ RebarConfig = [{profiles, [{hooks, [{pre_hooks, [{compile, "mkdir blah"}]}]}]}],
+ rebar_test_utils:create_config(AppDir, RebarConfig),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+ rebar_test_utils:run_and_check(Config, RebarConfig, ["as", "hooks", "compile"], {ok, [{app, Name, valid}]}).
+
deps_hook_namespace(Config) ->
mock_git_resource:mock([{deps, [{some_dep, "0.0.1"}]}]),
Deps = rebar_test_utils:expand_deps(git, [{"some_dep", "0.0.1", []}]),
diff --git a/test/rebar_pkg_SUITE.erl b/test/rebar_pkg_SUITE.erl
index 30cc0a8..32873c8 100644
--- a/test/rebar_pkg_SUITE.erl
+++ b/test/rebar_pkg_SUITE.erl
@@ -287,7 +287,7 @@ mock_config(Name, Config) ->
unmock_config(Config) ->
meck:unload(),
- ets:delete(?config(mock_table, Config)).
+ catch ets:delete(?config(mock_table, Config)).
copy_to_cache({Pkg,Vsn}, Config) ->
Name = <<Pkg/binary, "-", Vsn/binary, ".tar">>,
diff --git a/test/rebar_profiles_SUITE.erl b/test/rebar_profiles_SUITE.erl
index ed492a9..9ffaf98 100644
--- a/test/rebar_profiles_SUITE.erl
+++ b/test/rebar_profiles_SUITE.erl
@@ -25,7 +25,8 @@
test_profile_erl_opts_order_2/1,
test_profile_erl_opts_order_3/1,
test_profile_erl_opts_order_4/1,
- test_profile_erl_opts_order_5/1]).
+ test_profile_erl_opts_order_5/1,
+ first_files_exception/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -46,7 +47,8 @@ all() ->
test_profile_erl_opts_order_2,
test_profile_erl_opts_order_3,
test_profile_erl_opts_order_4,
- test_profile_erl_opts_order_5].
+ test_profile_erl_opts_order_5,
+ first_files_exception].
init_per_suite(Config) ->
application:start(meck),
@@ -468,6 +470,25 @@ test_profile_erl_opts_order_5(Config) ->
Opt = last_erl_opt(Opts, [warn_export_all, nowarn_export_all], undefined),
warn_export_all = Opt.
+first_files_exception(_Config) ->
+ RebarConfig = [{erl_first_files, ["c","a","b"]},
+ {mib_first_files, ["c","a","b"]},
+ {other, ["c","a","b"]},
+ {profiles,
+ [{profile2, [{erl_first_files, ["a","e"]},
+ {mib_first_files, ["a","e"]},
+ {other, ["a","e"]}
+ ]}]}],
+ State = rebar_state:new(RebarConfig),
+ State1 = rebar_state:apply_profiles(State, [profile2]),
+
+ %% Combine lists
+ ?assertEqual(["a","b","c","e"], rebar_state:get(State1, other)),
+ %% there is no specific reason not to dedupe "a" here aside from "this is how it is"
+ ?assertEqual(["c","a","b","a","e"], rebar_state:get(State1, erl_first_files)),
+ ?assertEqual(["c","a","b","a","e"], rebar_state:get(State1, mib_first_files)),
+ ok.
+
get_compiled_profile_erl_opts(Profiles, Config) ->
AppDir = ?config(apps, Config),
PStrs = [atom_to_list(P) || P <- Profiles],
diff --git a/test/rebar_release_SUITE.erl b/test/rebar_release_SUITE.erl
index 1125a7e..e41339b 100644
--- a/test/rebar_release_SUITE.erl
+++ b/test/rebar_release_SUITE.erl
@@ -11,6 +11,7 @@ all() -> [release,
profile_ordering_sys_config_extend_3_tuple_merge,
extend_release,
user_output_dir, profile_overlays,
+ profile_overlay_merge,
overlay_vars].
init_per_testcase(Case, Config0) ->
@@ -217,6 +218,30 @@ profile_overlays(Config) ->
{dir, filename:join(ReleaseDir, "randomdir")}]}
).
+profile_overlay_merge (_Config) ->
+ % when profile and relx overlays both exist, the profile overlays should be
+ % first, then the relx overlays, all the rest of the config should come
+ % after, rebar_relx:merge_overlays/1 should do this.
+ RelxOverlay = [{mkdir, "1_from_relx"}, {mkdir, "2_from_relx"}],
+ ProfileOverlay = [{mkdir, "0_from_other_profile"}],
+ OtherConfig = [{other1, config}, {other2, config}],
+
+ % test with no overlays
+ ?assertEqual([{overlay,[]}] ++ OtherConfig,
+ rebar_relx:merge_overlays(OtherConfig)),
+
+ % test with relx only, just move overlays to the top
+ RelxOnly = OtherConfig ++ [{overlay, RelxOverlay}],
+ ?assertEqual([{overlay, RelxOverlay}]++OtherConfig,
+ rebar_relx:merge_overlays(RelxOnly)),
+
+ % now test with a profile (profiles end up after relx overlays
+ ProfilesToMerge = OtherConfig ++
+ [{overlay, RelxOverlay},
+ {overlay, ProfileOverlay}],
+ ?assertEqual([{overlay, ProfileOverlay ++ RelxOverlay}] ++ OtherConfig,
+ rebar_relx:merge_overlays(ProfilesToMerge)).
+
overlay_vars(Config) ->
AppDir = ?config(apps, Config),
Name = ?config(name, Config),
diff --git a/test/rebar_src_dirs_SUITE.erl b/test/rebar_src_dirs_SUITE.erl
index f854a94..bc22160 100644
--- a/test/rebar_src_dirs_SUITE.erl
+++ b/test/rebar_src_dirs_SUITE.erl
@@ -11,12 +11,16 @@
src_dirs_in_erl_opts/1,
extra_src_dirs_in_erl_opts/1,
src_dirs_at_root_and_in_erl_opts/1,
+ dupe_src_dirs_at_root_and_in_erl_opts/1,
extra_src_dirs_at_root_and_in_erl_opts/1,
build_basic_app/1,
build_multi_apps/1,
- src_dir_takes_precedence_over_extra/1]).
+ src_dir_takes_precedence_over_extra/1,
+ src_dir_checkout_dep/1,
+ app_src_info/1]).
-include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
suite() ->
[].
@@ -35,8 +39,11 @@ end_per_testcase(_, _Config) -> ok.
all() ->
[src_dirs_at_root, extra_src_dirs_at_root,
src_dirs_in_erl_opts, extra_src_dirs_in_erl_opts,
- src_dirs_at_root_and_in_erl_opts, extra_src_dirs_at_root_and_in_erl_opts,
- build_basic_app, build_multi_apps, src_dir_takes_precedence_over_extra].
+ src_dirs_at_root_and_in_erl_opts,
+ dupe_src_dirs_at_root_and_in_erl_opts,
+ extra_src_dirs_at_root_and_in_erl_opts,
+ build_basic_app, build_multi_apps, src_dir_takes_precedence_over_extra,
+ src_dir_checkout_dep, app_src_info].
src_dirs_at_root(Config) ->
AppDir = ?config(apps, Config),
@@ -93,15 +100,47 @@ extra_src_dirs_in_erl_opts(Config) ->
src_dirs_at_root_and_in_erl_opts(Config) ->
AppDir = ?config(apps, Config),
- Name = rebar_test_utils:create_random_name("app1_"),
+ Name = rebar_test_utils:create_random_name("src_dirs_root_erlopts_"),
Vsn = rebar_test_utils:create_random_vsn(),
rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, {src_dirs, ["baz", "qux"]}],
+ %% move the .app.src file to one of the subdirs, out of src/
+ filelib:ensure_dir(filename:join([AppDir, "qux", "fake"])),
+ rebar_file_utils:mv(filename:join([AppDir, "src", Name ++ ".app.src"]),
+ filename:join([AppDir, "qux", Name ++ ".app.src"])),
+
{ok, State} = rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
- ["bar", "baz", "foo", "qux"] = rebar_dir:src_dirs(rebar_state:opts(State), []).
+ ["bar", "baz", "foo", "qux"] = rebar_dir:src_dirs(rebar_state:opts(State), []),
+ rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"],
+ {ok, [{app, Name}]}),
+ ok.
+
+dupe_src_dirs_at_root_and_in_erl_opts(Config) ->
+ AppDir = ?config(apps, Config),
+
+ Name = rebar_test_utils:create_random_name("dupe_src_dirs_root_erlopts_"),
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]),
+
+ RebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]}, {src_dirs, ["baz", "qux"]}],
+
+ %% move the .app.src file to one of the subdirs, out of src/
+ filelib:ensure_dir(filename:join([AppDir, "qux", "fake"])),
+ filelib:ensure_dir(filename:join([AppDir, "foo", "fake"])),
+ Src1 = filename:join([AppDir, "qux", Name ++ ".app.src"]),
+ Src2 = filename:join([AppDir, "foo", Name ++ ".app.src"]),
+ rebar_file_utils:mv(filename:join([AppDir, "src", Name ++ ".app.src"]),
+ Src1),
+ %% Then copy it over to create a conflict with dupes
+ file:copy(Src1, Src2),
+
+ {error, {rebar_prv_app_discovery, {multiple_app_files, [Src2, Src1]}}} =
+ rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], return),
+
+ ok.
extra_src_dirs_at_root_and_in_erl_opts(Config) ->
AppDir = ?config(apps, Config),
@@ -236,3 +275,52 @@ src_dir_takes_precedence_over_extra(Config) ->
[{application, _, KVs}] = App,
Mods = proplists:get_value(modules, KVs),
true = lists:member(extra, Mods).
+
+src_dir_checkout_dep(Config) ->
+ AppDir = ?config(apps, Config),
+ AppName = rebar_test_utils:create_random_name("src_dir_checkout_app"),
+ DepName = rebar_test_utils:create_random_name("src_dir_checkout_dep"),
+ AtomDep = list_to_atom(DepName),
+
+ Vsn = rebar_test_utils:create_random_vsn(),
+ rebar_test_utils:create_app(AppDir, AppName, Vsn, [kernel, stdlib]),
+ RebarConfig = [{deps, [AtomDep]}],
+
+ DepDir = filename:join([?config(checkouts, Config), DepName]),
+ ct:pal("checkouts dir: ~p", [DepDir]),
+ rebar_test_utils:create_app(DepDir, DepName, Vsn, [kernel, stdlib]),
+
+
+ %% move the .app.src file to one of the subdirs, out of src/
+ rebar_file_utils:mv(filename:join([DepDir, "src"]),
+ filename:join([DepDir, "qux"])),
+ DepRebarConfig = [{erl_opts, [{src_dirs, ["foo", "bar"]}]},
+ {src_dirs, ["baz", "qux"]}],
+ file:write_file(filename:join([DepDir, "rebar.config"]),
+ io_lib:format("~p.~n~p.~n", DepRebarConfig)),
+
+ rebar_test_utils:run_and_check(
+ Config, RebarConfig, ["compile"],
+ {ok, [{checkout, DepName}, {app, AppName}]}
+ ),
+ ok.
+
+app_src_info(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ AppName1 = rebar_test_utils:create_random_name("app_src_info"),
+ AppDir1 = filename:join(PrivDir, AppName1),
+ {ok, Info1} = rebar_app_info:new(AppName1, "1.0.0", AppDir1),
+ AppSrc1 = filename:join([AppDir1, "src", AppName1 ++ ".app.src"]),
+ ok = filelib:ensure_dir(AppSrc1),
+ ok = file:write_file(AppSrc1, "[]."),
+ ?assertEqual(AppSrc1, rebar_app_info:app_file_src(Info1)),
+
+ AppName2 = rebar_test_utils:create_random_name("app_src_info"),
+ AppDir2 = filename:join(PrivDir, AppName2),
+ {ok, Info2Tmp} = rebar_app_info:new(AppName2, "1.0.0", AppDir2),
+ Info2 = rebar_app_info:set(Info2Tmp, src_dirs, ["foo", "bar", "baz"]),
+ AppSrc2 = filename:join([AppDir2, "bar", AppName2 ++ ".app.src"]),
+ ok = filelib:ensure_dir(AppSrc2),
+ ok = file:write_file(AppSrc2, "[]."),
+ ?assertEqual(AppSrc2, rebar_app_info:app_file_src(Info2)),
+ ok.
diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl
index 8c177c9..0ccec56 100644
--- a/test/rebar_test_utils.erl
+++ b/test/rebar_test_utils.erl
@@ -218,7 +218,7 @@ check_results(AppDir, Expected, ProfileRun) ->
BuildDirs = filelib:wildcard(filename:join([AppDir, "_build", ProfileRun, "lib", "*"])),
PluginDirs = filelib:wildcard(filename:join([AppDir, "_build", ProfileRun, "plugins", "*"])),
GlobalPluginDirs = filelib:wildcard(filename:join([AppDir, "global", "plugins", "*"])),
- CheckoutsDir = filename:join([AppDir, "_checkouts", "*"]),
+ CheckoutsDirs = filelib:wildcard(filename:join([AppDir, "_checkouts", "*"])),
LockFile = filename:join([AppDir, "rebar.lock"]),
Locks = lists:flatten(rebar_config:consult_lock_file(LockFile)),
@@ -230,7 +230,7 @@ check_results(AppDir, Expected, ProfileRun) ->
Deps = rebar_app_discover:find_apps(BuildDirs, all),
DepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Deps],
- Checkouts = rebar_app_discover:find_apps([CheckoutsDir], all),
+ Checkouts = rebar_app_discover:find_apps(CheckoutsDirs, all),
CheckoutsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Checkouts],
Plugins = rebar_app_discover:find_apps(PluginDirs, all),
PluginsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Plugins],
@@ -349,7 +349,7 @@ check_results(AppDir, Expected, ProfileRun) ->
iolist_to_binary(LockVsn))
end
; ({release, Name, Vsn, ExpectedDevMode}) ->
- ct:pal("Release: ~p-~s", [Name, Vsn]),
+ ct:pal("Release: ~p-~ts", [Name, Vsn]),
{ok, Cwd} = file:get_cwd(),
try
file:set_cwd(AppDir),
@@ -377,14 +377,14 @@ check_results(AppDir, Expected, ProfileRun) ->
file:set_cwd(Cwd)
end
; ({tar, Name, Vsn}) ->
- ct:pal("Tarball: ~s-~s", [Name, Vsn]),
+ ct:pal("Tarball: ~ts-~ts", [Name, Vsn]),
Tarball = filename:join([AppDir, "_build", "rel", Name, Name++"-"++Vsn++".tar.gz"]),
?assertNotEqual([], filelib:is_file(Tarball))
; ({file, Filename}) ->
- ct:pal("Filename: ~s", [Filename]),
+ ct:pal("Filename: ~ts", [Filename]),
?assert(filelib:is_file(Filename))
; ({dir, Dirname}) ->
- ct:pal("Directory: ~s", [Dirname]),
+ ct:pal("Directory: ~ts", [Dirname]),
?assert(filelib:is_dir(Dirname))
end, Expected).
diff --git a/test/rebar_upgrade_SUITE.erl b/test/rebar_upgrade_SUITE.erl
index 66e1fdf..45a7433 100644
--- a/test/rebar_upgrade_SUITE.erl
+++ b/test/rebar_upgrade_SUITE.erl
@@ -11,7 +11,8 @@ groups() ->
triplet_a, triplet_b, triplet_c,
tree_a, tree_b, tree_c, tree_c2, tree_cj, tree_ac, tree_all,
delete_d, promote, stable_lock, fwd_lock,
- compile_upgrade_parity, umbrella_config]},
+ compile_upgrade_parity, umbrella_config,
+ profiles, profiles_exclusion]},
{git, [], [{group, all}]},
{pkg, [], [{group, all}]}].
@@ -78,6 +79,23 @@ setup_project(Case=umbrella_config, Config0, Deps, UpDeps) ->
[{rebarconfig, TopConf},
{rebarumbrella, RebarConf},
{next_top_deps, rebar_test_utils:top_level_deps(UpDeps)} | Config];
+setup_project(Case, Config0, Deps, UpDeps) when Case == profiles;
+ Case == profiles_exclusion ->
+ DepsType = ?config(deps_type, Config0),
+ NameRoot = atom_to_list(Case)++"_"++atom_to_list(DepsType),
+ Config = rebar_test_utils:init_rebar_state(Config0, NameRoot++"_"),
+ AppDir = filename:join([?config(apps, Config), "apps", NameRoot]),
+ rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]),
+ [Top|ProfileDeps] = rebar_test_utils:top_level_deps(Deps),
+ RebarConf = rebar_test_utils:create_config(AppDir, [
+ {deps, [Top]},
+ {profiles, [{fake, [{deps, ProfileDeps}]}]}
+ ]),
+ [NextTop|NextPDeps] = rebar_test_utils:top_level_deps(UpDeps),
+ NextConfig = [{deps, [NextTop]},
+ {profiles, [{fake, [{deps, NextPDeps}]}]}],
+ [{rebarconfig, RebarConf},
+ {next_config, NextConfig} | Config];
setup_project(Case, Config0, Deps, UpDeps) ->
DepsType = ?config(deps_type, Config0),
Config = rebar_test_utils:init_rebar_state(
@@ -454,7 +472,47 @@ upgrades(umbrella_config) ->
{[{"A", "1", []}],
[{"A", "2", []}],
["A"],
- {"A", [{"A","2"}]}}.
+ {"A", [{"A","2"}]}};
+upgrades(profiles) ->
+ %% Ensure that we can unlock deps under a given profile;
+ %% B and C should both be in a custom profile
+ %% and must not be locked.
+ {[{"A", "1", [{"D",[]},
+ {"E","3",[]}]},
+ {"B", "1", [{"F","1",[]},
+ {"G",[]}]},
+ {"C", "0", [{"H","3",[]},
+ {"I",[]}]}],
+ [{"A", "2", [{"D",[]},
+ {"E","2",[]}]},
+ {"B", "2", [{"F","2",[]},
+ {"G",[]}]},
+ {"C", "1", [{"H","4",[]},
+ {"I",[]}]}],
+ ["A","B","C","E","F","H"],
+ {"C", [{"A","1"}, "D", {"E","3"},
+ {"B","2"}, {"F","2"}, "G",
+ {"C","1"}, {"H","4"}, "I"]}};
+upgrades(profiles_exclusion) ->
+ %% Ensure that we can unlock deps under a given profile;
+ %% B and C should both be in a custom profile
+ %% and must not be locked.
+ {[{"A", "1", [{"D",[]},
+ {"E","3",[]}]},
+ {"B", "1", [{"F","1",[]},
+ {"G",[]}]},
+ {"C", "0", [{"H","3",[]},
+ {"I",[]}]}],
+ [{"A", "2", [{"D",[]},
+ {"E","2",[]}]},
+ {"B", "2", [{"F","2",[]},
+ {"G",[]}]},
+ {"C", "1", [{"H","4",[]},
+ {"I",[]}]}],
+ ["A","B","C","E","F","H"],
+ {"A", [{"A","1"}, "D", {"E","3"},
+ {"B","2"}, {"F","2"}, "G",
+ {"C","1"}, {"H","4"}, "I"]}}.
%% TODO: add a test that verifies that unlocking files and then
%% running the upgrade code is enough to properly upgrade things.
@@ -613,6 +671,37 @@ umbrella_config(Config) ->
),
meck:unload(rebar_prv_upgrade).
+profiles(Config) ->
+ apply(?config(mock, Config), []),
+ {ok, TopConfig} = file:consult(?config(rebarconfig, Config)),
+ %% Install dependencies before re-mocking for an upgrade
+ rebar_test_utils:run_and_check(Config, TopConfig, ["lock"], {ok, []}),
+ %% Install test deps along with them
+ rebar_test_utils:run_and_check(Config, TopConfig, ["as","fake","lock"], {ok, []}),
+ {App, Unlocks} = ?config(expected, Config),
+ ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
+ Expectation = case Unlocks of
+ {error, Term} -> {error, Term};
+ _ -> {ok, [T || T <- Unlocks,
+ element(1,T) == dep orelse
+ lists:member(element(2,T), ["A","D","E"])]}
+ end,
+
+ meck:new(rebar_prv_app_discovery, [passthrough]),
+ meck:expect(rebar_prv_app_discovery, do, fun(S) ->
+ apply(?config(mock_update, Config), []),
+ meck:passthrough([S])
+ end),
+ NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
+ ?config(next_config, Config)),
+ {ok, NewRebarConfig} = file:consult(NewRebarConf),
+ rebar_test_utils:run_and_check(
+ Config, NewRebarConfig, ["as","fake","upgrade", App], Expectation
+ ),
+ meck:unload(rebar_prv_app_discovery).
+
+profiles_exclusion(Config) -> profiles(Config).
+
run(Config) ->
apply(?config(mock, Config), []),
ConfigPath = ?config(rebarconfig, Config),
diff --git a/test/rebar_xref_SUITE.erl b/test/rebar_xref_SUITE.erl
index 09f73a7..f052fa4 100644
--- a/test/rebar_xref_SUITE.erl
+++ b/test/rebar_xref_SUITE.erl
@@ -9,7 +9,9 @@
end_per_testcase/2,
all/0,
xref_test/1,
- xref_ignore_test/1]).
+ xref_ignore_test/1,
+ xref_dep_hook/1,
+ xref_undef_behaviour/1]).
-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
@@ -28,6 +30,15 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
ok.
+init_per_testcase(xref_dep_hook, Config) ->
+ Src = filename:join([?config(data_dir, Config), "recursive"]),
+ Dst = filename:join([?config(priv_dir, Config), "recursive"]),
+ ok = rebar_file_utils:cp_r([Src], Dst),
+ GlobalDir = filename:join([?config(priv_dir, Config), "cache"]),
+ State = rebar_state:new([{base_dir, filename:join([Dst, "_build"])}
+ ,{global_rebar_dir, GlobalDir}
+ ,{root_dir, Dst}]),
+ [{apps, Dst}, {state, State} | Config];
init_per_testcase(Case, Config) ->
UpdConfig = rebar_test_utils:init_rebar_state(Config),
AppDir = ?config(apps, UpdConfig),
@@ -48,7 +59,7 @@ end_per_testcase(_, _Config) ->
ok.
all() ->
- [xref_test, xref_ignore_test].
+ [xref_test, xref_ignore_test, xref_dep_hook, xref_undef_behaviour].
%% ===================================================================
%% Test cases
@@ -70,6 +81,21 @@ xref_ignore_test(Config) ->
Result = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), ["xref"]),
verify_results(xref_ignore_test, Name, Result).
+xref_dep_hook(Config) ->
+ rebar_test_utils:run_and_check(Config, [], ["compile"], {ok, []}).
+
+xref_undef_behaviour(Config) ->
+ AppDir = ?config(apps, Config),
+ State = ?config(state, Config),
+ Name = ?config(app_name, Config),
+ RebarConfig = ?config(rebar_config, Config),
+ %% delete one of the behaviours, which should create new warnings
+ delete_src_file(AppDir, Name, behaviour1),
+ %% just ensure this does not crash
+ Result = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), ["xref"]),
+ verify_results(xref_undef_behaviour, Name, Result).
+
+
%% ===================================================================
%% Helper functions
%% ===================================================================
@@ -110,6 +136,31 @@ verify_test_results(xref_test, AppName, XrefResults, _QueryResults) ->
?assertNot(lists:member({MyMod, bh2_a, 1}, ExportsNotUsed)),
?assertNot(lists:member({MyMod, bh2_b, 1}, ExportsNotUsed)),
ok;
+verify_test_results(xref_undef_behaviour, AppName, XrefResults, _QueryResults) ->
+ AppModules = ["behaviour2", "mymod", "othermod", "somemod"],
+ [Behaviour2Mod, MyMod, OtherMod, SomeMod] =
+ [list_to_atom(AppName ++ "_" ++ Mod) || Mod <- AppModules],
+ UndefFuns = proplists:get_value(undefined_functions, XrefResults),
+ UndefFunCalls = proplists:get_value(undefined_function_calls, XrefResults),
+ LocalsNotUsed = proplists:get_value(locals_not_used, XrefResults),
+ ExportsNotUsed = proplists:get_value(exports_not_used, XrefResults),
+ DeprecatedFuns = proplists:get_value(deprecated_functions, XrefResults),
+ DeprecatedFunCalls = proplists:get_value(deprecated_function_calls, XrefResults),
+ ?assert(lists:member({SomeMod, notavailable, 1}, UndefFuns)),
+ ?assert(lists:member({{OtherMod, somefunc, 0}, {SomeMod, notavailable, 1}},
+ UndefFunCalls)),
+ ?assert(lists:member({MyMod, fdeprecated, 0}, DeprecatedFuns)),
+ ?assert(lists:member({{OtherMod, somefunc, 0}, {MyMod, fdeprecated, 0}},
+ DeprecatedFunCalls)),
+ ?assert(lists:member({MyMod, localfunc2, 0}, LocalsNotUsed)),
+ ?assert(lists:member({Behaviour2Mod, behaviour_info, 1}, ExportsNotUsed)),
+ ?assert(lists:member({MyMod, other2, 1}, ExportsNotUsed)),
+ ?assert(lists:member({OtherMod, somefunc, 0}, ExportsNotUsed)),
+ ?assert(lists:member({MyMod, bh1_a, 1}, ExportsNotUsed)),
+ ?assert(lists:member({MyMod, bh1_b, 1}, ExportsNotUsed)),
+ ?assertNot(lists:member({MyMod, bh2_a, 1}, ExportsNotUsed)),
+ ?assertNot(lists:member({MyMod, bh2_b, 1}, ExportsNotUsed)),
+ ok;
verify_test_results(xref_ignore_test, AppName, XrefResults, _QueryResults) ->
AppModules = ["behaviour1", "behaviour2", "mymod", "othermod", "somemod"],
[_Behaviour1Mod, _Behaviour2Mod, _MyMod, _OtherMod, SomeMod] =
@@ -128,6 +179,10 @@ write_src_file(Dir, AppName, Module, IgnoreXref) ->
ok = filelib:ensure_dir(Erl),
ok = ec_file:write(Erl, get_module_body(Module, AppName, IgnoreXref)).
+delete_src_file(Dir, AppName, Module) ->
+ Erl = filename:join([Dir, "src", module_name(AppName, Module)]),
+ ok = file:delete(Erl).
+
module_name(AppName, Module) ->
lists:flatten([AppName, "_", atom_to_list(Module), ".erl"]).
diff --git a/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/rebar.config b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/rebar.config
new file mode 100644
index 0000000..cf48edf
--- /dev/null
+++ b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/rebar.config
@@ -0,0 +1,12 @@
+{erl_opts, [debug_info]}.
+{deps, []}.
+
+{xref_checks,[
+ undefined_function_calls,
+ undefined_functions,
+ locals_not_used,
+ deprecated_function_calls,
+ deprecated_functions
+]}.
+
+{provider_hooks, [{post, [{compile, xref}]}]}.
diff --git a/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1.app.src b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1.app.src
new file mode 100644
index 0000000..b935082
--- /dev/null
+++ b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1.app.src
@@ -0,0 +1,16 @@
+{application, rebar_issue1,
+ [{description, "An OTP application"},
+ {vsn, "0.1.0"},
+ {registered, []},
+ {mod, { rebar_issue1_app, []}},
+ {applications,
+ [kernel,
+ stdlib
+ ]},
+ {env,[]},
+ {modules, []},
+
+ {maintainers, []},
+ {licenses, []},
+ {links, []}
+ ]}.
diff --git a/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_app.erl b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_app.erl
new file mode 100644
index 0000000..78c88c1
--- /dev/null
+++ b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_app.erl
@@ -0,0 +1,26 @@
+%%%-------------------------------------------------------------------
+%% @doc rebar_issue1 public API
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(rebar_issue1_app).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+start(_StartType, _StartArgs) ->
+ rebar_issue1_sup:start_link().
+
+%%--------------------------------------------------------------------
+stop(_State) ->
+ ok.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
diff --git a/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_sup.erl b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_sup.erl
new file mode 100644
index 0000000..6e5a9f8
--- /dev/null
+++ b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue1/src/rebar_issue1_sup.erl
@@ -0,0 +1,35 @@
+%%%-------------------------------------------------------------------
+%% @doc rebar_issue1 top level supervisor.
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(rebar_issue1_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+-define(SERVER, ?MODULE).
+
+%%====================================================================
+%% API functions
+%%====================================================================
+
+start_link() ->
+ supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+
+%%====================================================================
+%% Supervisor callbacks
+%%====================================================================
+
+%% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules}
+init([]) ->
+ {ok, { {one_for_all, 0, 1}, []} }.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
diff --git a/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2.app.src b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2.app.src
new file mode 100644
index 0000000..59ffa35
--- /dev/null
+++ b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2.app.src
@@ -0,0 +1,17 @@
+{application, rebar_issue2,
+ [{description, "An OTP application"},
+ {vsn, "0.1.0"},
+ {registered, []},
+ {mod, { rebar_issue2_app, []}},
+ {applications,
+ [kernel,
+ stdlib,
+ rebar_issue1
+ ]},
+ {env,[]},
+ {modules, []},
+
+ {maintainers, []},
+ {licenses, []},
+ {links, []}
+ ]}.
diff --git a/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_app.erl b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_app.erl
new file mode 100644
index 0000000..968966c
--- /dev/null
+++ b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_app.erl
@@ -0,0 +1,26 @@
+%%%-------------------------------------------------------------------
+%% @doc rebar_issue2 public API
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(rebar_issue2_app).
+
+-behaviour(application).
+
+%% Application callbacks
+-export([start/2, stop/1]).
+
+%%====================================================================
+%% API
+%%====================================================================
+
+start(_StartType, _StartArgs) ->
+ rebar_issue2_sup:start_link().
+
+%%--------------------------------------------------------------------
+stop(_State) ->
+ ok.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
diff --git a/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_sup.erl b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_sup.erl
new file mode 100644
index 0000000..3673548
--- /dev/null
+++ b/test/rebar_xref_SUITE_data/recursive/apps/rebar_issue2/src/rebar_issue2_sup.erl
@@ -0,0 +1,35 @@
+%%%-------------------------------------------------------------------
+%% @doc rebar_issue2 top level supervisor.
+%% @end
+%%%-------------------------------------------------------------------
+
+-module(rebar_issue2_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+-define(SERVER, ?MODULE).
+
+%%====================================================================
+%% API functions
+%%====================================================================
+
+start_link() ->
+ supervisor:start_link({local, ?SERVER}, ?MODULE, []).
+
+%%====================================================================
+%% Supervisor callbacks
+%%====================================================================
+
+%% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules}
+init([]) ->
+ {ok, { {one_for_all, 0, 1}, []} }.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================