diff options
Diffstat (limited to 'test/rebar_install_deps_SUITE.erl')
-rw-r--r-- | test/rebar_install_deps_SUITE.erl | 225 |
1 files changed, 191 insertions, 34 deletions
diff --git a/test/rebar_install_deps_SUITE.erl b/test/rebar_install_deps_SUITE.erl index 4e6c3d9..cf3b260 100644 --- a/test/rebar_install_deps_SUITE.erl +++ b/test/rebar_install_deps_SUITE.erl @@ -4,16 +4,24 @@ -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). -all() -> [{group, git}, {group, pkg}]. +all() -> [{group, git}, {group, pkg}, {group, mixed}]. groups() -> - [{all, [], [flat, pick_highest_left, pick_highest_right, - pick_smallest1, pick_smallest2, - circular1, circular2, circular_skip, - fail_conflict, default_profile, nondefault_profile, - nondefault_pick_highest]}, - {git, [], [{group, all}]}, - {pkg, [], [{group, all}]}]. + [{unique, [], [flat, pick_highest_left, pick_highest_right, + pick_smallest1, pick_smallest2, + circular1, circular2, circular_skip, + fail_conflict, default_profile, nondefault_profile, + nondefault_pick_highest]}, + {git, [], [{group, unique}]}, + {pkg, [], [{group, unique}]}, + {mixed, [], [ + m_flat1, m_flat2, m_circular1, m_circular2, m_circular3, + m_pick_source1, m_pick_source2, m_pick_source3, + m_pick_source4, m_pick_source5, m_source_to_pkg, + m_pkg_level1, m_pkg_level2, + m_pkg_src_override + ]} + ]. init_per_suite(Config) -> application:start(meck), @@ -26,19 +34,33 @@ init_per_group(git, Config) -> [{deps_type, git} | Config]; init_per_group(pkg, Config) -> [{deps_type, pkg} | Config]; +init_per_group(mixed, Config) -> + [{deps_type, mixed} | Config]; init_per_group(_, Config) -> Config. end_per_group(_, Config) -> Config. -init_per_testcase(Case, Config) -> +init_per_testcase(Case, Config) when is_atom(Case) -> + DepsType = ?config(deps_type, Config), + init_per_testcase({DepsType, Case}, Config); +init_per_testcase({mixed, Case}, Config) -> + {Deps, Warnings, Expect} = mdeps(Case), + Expected = case Expect of + {ok, List} -> {ok, format_expected_mdeps(List)}; + Other -> Other + end, + mock_warnings(), + [{expect, Expected}, + {warnings, format_expected_mixed_warnings(Warnings)} + | setup_project(Case, Config, rebar_test_utils:expand_deps(mixed, Deps))]; +init_per_testcase({DepsType, Case}, Config) -> {Deps, Warnings, Expect} = deps(Case), Expected = case Expect of {ok, List} -> {ok, format_expected_deps(List)}; Other -> Other end, - DepsType = ?config(deps_type, Config), mock_warnings(), [{expect, Expected}, {warnings, Warnings} @@ -54,6 +76,32 @@ format_expected_deps(Deps) -> N -> [{dep, N}, {lock, N}] end || Dep <- Deps]). +format_expected_mdeps(Deps) -> + %% for mixed deps, lowercase is a package, uppercase is source. + %% We can't check which was used from the dep, but the lock contains + %% the type and we can use that information. + lists:append([ + case Dep of + {N,V} when hd(N) >= $a, hd(N) =< $z -> + UN = string:to_upper(N), + [{dep, UN, V}, {lock, pkg, UN, V}]; + {N,V} when hd(N) >= $A, hd(N) =< $Z -> + [{dep, N, V}, {lock, src, N, V}]; + N when hd(N) >= $a, hd(N) =< $z -> + UN = string:to_upper(N), + [{dep, UN}, {lock, pkg, UN, "0.0.0"}]; + N when hd(N) >= $A, hd(N) =< $Z -> + [{dep, N}, {lock, src, N, "0.0.0"}] + end || Dep <- Deps]). + +format_expected_mixed_warnings(Warnings) -> + [case W of + {N, Vsn} when hd(N) >= $a, hd(N) =< $z -> {pkg, string:to_upper(N), Vsn}; + {N, Vsn} when hd(N) >= $A, hd(N) =< $Z -> {src, N, Vsn}; + N when hd(N) >= $a, hd(N) =< $z -> {pkg, string:to_upper(N), "0.0.0"}; + N when hd(N) >= $A, hd(N) =< $Z -> {src, N, "0.0.0"} + end || W <- Warnings]. + %% format: %% {Spec, %% [Warning], @@ -131,6 +179,78 @@ deps(nondefault_pick_highest) -> %% This is all handled in setup_project {[],[],{ok,[]}}. +%% format: +%% Same as `deps/1' except "A" is a source dep +%% and "a" is a package dep. +mdeps(m_flat1) -> + {[{"c", []}, + {"B", []}], + [], + {ok, ["B","c"]}}; +mdeps(m_flat2) -> + {[{"B", []}, + {"c", []}], + [], + {ok, ["B","c"]}}; +mdeps(m_circular1) -> + {[{"b", [{"a",[]}]}], % "A" is the top app + [], + {error, {rebar_prv_install_deps, {cycles, [[<<"A">>,<<"B">>]]}}}}; +mdeps(m_circular2) -> + {[{"B", [{"c", [{"b", []}]}]}], + [], + {error, {rebar_prv_install_deps, {cycles, [[<<"B">>,<<"C">>]]}}}}; +mdeps(m_circular3) -> + %% Spot the circular dep due to being to low in the deps tree + %% but as a source dep, taking precedence over packages + {[{"B", [{"C", "2", [{"B", []}]}]}, + {"c", "1", [{"d",[]}]}], + [], + {error, {rebar_prv_install_deps, {cycles, [[<<"B">>,<<"C">>]]}}}}; +mdeps(m_pick_source1) -> + {[{"B", [{"D", []}]}, + {"c", [{"d", []}]}], + ["d"], + {ok, ["B", "c", "D"]}}; +mdeps(m_pick_source2) -> + {[{"b", [{"d", []}]}, + {"C", [{"D", []}]}], + ["d"], + {ok, ["b", "C", "D"]}}; +mdeps(m_pick_source3) -> + {[{"b", []}, + {"B", []}], + ["b"], + {ok, ["B"]}}; +mdeps(m_pick_source4) -> + {[{"B", []}, + {"b", []}], + ["b"], + {ok, ["B"]}}; +mdeps(m_pick_source5) -> + {[{"B", [{"d", []}]}, + {"C", [{"D", []}]}], + ["d"], + {ok, ["B", "C", "D"]}}; +mdeps(m_source_to_pkg) -> + {[{"B", [{"c",[{"d", []}]}]}], + [], + {ok, ["B", "c", "d"]}}; +mdeps(m_pkg_level1) -> + {[{"B", [{"D", [{"e", "2", []}]}]}, + {"C", [{"e", "1", []}]}], + [{"e","2"}], + {ok, ["B","C","D",{"e","1"}]}}; +mdeps(m_pkg_level2) -> + {[{"B", [{"e", "1", []}]}, + {"C", [{"D", [{"e", "2", []}]}]}], + [{"e","2"}], + {ok, ["B","C","D",{"e","1"}]}}; +mdeps(m_pkg_src_override) -> + %% This is all handled in setup_project + {[],[],{ok,[]}}. + + setup_project(fail_conflict, Config0, Deps) -> DepsType = ?config(deps_type, Config0), Config = rebar_test_utils:init_rebar_state( @@ -142,12 +262,9 @@ setup_project(fail_conflict, Config0, Deps) -> TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}, {deps_error_on_conflict, true}]), - case DepsType of - git -> - mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(Deps)}]); - pkg -> - mock_pkg_resource:mock([{pkgdeps, rebar_test_utils:flat_pkgdeps(Deps)}]) - end, + {SrcDeps, PkgDeps} = rebar_test_utils:flat_deps(Deps), + mock_git_resource:mock([{deps, SrcDeps}]), + mock_pkg_resource:mock([{pkgdeps, PkgDeps}]), [{rebarconfig, RebarConf} | Config]; setup_project(nondefault_profile, Config0, Deps) -> DepsType = ?config(deps_type, Config0), @@ -161,12 +278,9 @@ setup_project(nondefault_profile, Config0, Deps) -> RebarConf = rebar_test_utils:create_config(AppDir, [{profiles, [ {nondef, [{deps, TopDeps}]} ]}]), - case DepsType of - git -> - mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(Deps)}]); - pkg -> - mock_pkg_resource:mock([{pkgdeps, rebar_test_utils:flat_pkgdeps(Deps)}]) - end, + {SrcDeps, PkgDeps} = rebar_test_utils:flat_deps(Deps), + mock_git_resource:mock([{deps, SrcDeps}]), + mock_pkg_resource:mock([{pkgdeps, PkgDeps}]), [{rebarconfig, RebarConf} | Config]; setup_project(nondefault_pick_highest, Config0, _) -> DepsType = ?config(deps_type, Config0), @@ -187,15 +301,30 @@ setup_project(nondefault_pick_highest, Config0, _) -> ), case DepsType of git -> - mock_git_resource:mock( - [{deps, rebar_test_utils:flat_deps(DefaultDeps ++ ProfileDeps)}] - ); + {SrcDeps, _} = rebar_test_utils:flat_deps(DefaultDeps++ProfileDeps), + mock_git_resource:mock([{deps, SrcDeps}]); pkg -> - mock_pkg_resource:mock( - [{pkgdeps, rebar_test_utils:flat_pkgdeps(DefaultDeps ++ ProfileDeps)}] - ) + {_, PkgDeps} = rebar_test_utils:flat_deps(DefaultDeps++ProfileDeps), + mock_pkg_resource:mock([{pkgdeps, PkgDeps}]) end, [{rebarconfig, RebarConf} | Config]; +setup_project(m_pkg_src_override, Config0, _) -> + Config = rebar_test_utils:init_rebar_state(Config0, "m_pkg_src_override_mixed_"), + AppDir = ?config(apps, Config), + rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), + DefaultDeps = rebar_test_utils:expand_deps(mixed, [{"b", [{"c", []}]}]), + OverrideDeps = rebar_test_utils:expand_deps(mixed, [{"C", []}]), + DefaultTop = rebar_test_utils:top_level_deps(DefaultDeps), + OverrideTop = rebar_test_utils:top_level_deps(OverrideDeps), + RebarConf = rebar_test_utils:create_config( + AppDir, + [{deps, DefaultTop}, + {overrides, [{override, b, [{deps, OverrideTop}]}]}] + ), + {SrcDeps,PkgDeps} = rebar_test_utils:flat_deps(DefaultDeps++OverrideDeps), + mock_git_resource:mock([{deps, SrcDeps}]), + mock_pkg_resource:mock([{pkgdeps, PkgDeps}]), + [{rebarconfig, RebarConf} | Config]; setup_project(Case, Config0, Deps) -> DepsType = ?config(deps_type, Config0), Config = rebar_test_utils:init_rebar_state( @@ -206,12 +335,9 @@ setup_project(Case, Config0, Deps) -> rebar_test_utils:create_app(AppDir, "A", "0.0.0", [kernel, stdlib]), TopDeps = rebar_test_utils:top_level_deps(Deps), RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]), - case DepsType of - git -> - mock_git_resource:mock([{deps, rebar_test_utils:flat_deps(Deps)}]); - pkg -> - mock_pkg_resource:mock([{pkgdeps, rebar_test_utils:flat_pkgdeps(Deps)}]) - end, + {SrcDeps, PkgDeps} = rebar_test_utils:flat_deps(Deps), + mock_git_resource:mock([{deps, SrcDeps}]), + mock_pkg_resource:mock([{pkgdeps, PkgDeps}]), [{rebarconfig, RebarConf} | Config]. mock_warnings() -> @@ -319,6 +445,33 @@ nondefault_pick_highest(Config) -> {ok, [{dep, "B"}, {lock, "B"}, {lock, "C", "1"}, {dep, "C", "2"}], "nondef"} ). +m_flat1(Config) -> run(Config). +m_flat2(Config) -> run(Config). +m_circular1(Config) -> run(Config). +m_circular2(Config) -> run(Config). +m_circular3(Config) -> run(Config). +m_pick_source1(Config) -> run(Config). +m_pick_source2(Config) -> run(Config). +m_pick_source3(Config) -> run(Config). +m_pick_source4(Config) -> run(Config). +m_pick_source5(Config) -> run(Config). +m_source_to_pkg(Config) -> run(Config). +m_pkg_level1(Config) -> run(Config). +m_pkg_level2(Config) -> run(Config). + + +m_pkg_src_override(Config) -> + %% Detect the invalid override where a package dep's are overriden + %% with source dependencies. We only test with overrides because + %% we trust the package index to be correct there and not introduce + %% that kind of error. + {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), + rebar_test_utils:run_and_check( + Config, RebarConfig, ["lock"], + {error, {rebar_prv_install_deps, + {source_dep_in_pkg, [<<"C">>,<<"b">>]}}} + ). + run(Config) -> {ok, RebarConfig} = file:consult(?config(rebarconfig, Config)), rebar_test_utils:run_and_check( @@ -336,6 +489,10 @@ error_calls() -> check_warnings(_, [], _) -> ok; +check_warnings(Warns, [{Type, Name, Vsn} | Rest], mixed) -> + ct:pal("Checking for warning ~p in ~p", [{Name,Vsn},Warns]), + ?assert(in_warnings(Type, Warns, Name, Vsn)), + check_warnings(Warns, Rest, mixed); check_warnings(Warns, [{Name, Vsn} | Rest], Type) -> ct:pal("Checking for warning ~p in ~p", [{Name,Vsn},Warns]), ?assert(in_warnings(Type, Warns, Name, Vsn)), |