diff options
Diffstat (limited to 'test')
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 +%%==================================================================== |