-module(rebar_upgrade_SUITE).
|
|
-include_lib("common_test/include/ct.hrl").
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
-compile(export_all).
|
|
|
|
all() -> [{group, git}].%, {group, pkg}].
|
|
|
|
groups() ->
|
|
[{all, [], [top, pair, triplet, tree]},
|
|
{git, [], [{group, all}]},
|
|
{pkg, [], [{group, all}]}].
|
|
|
|
init_per_suite(Config) ->
|
|
application:start(meck),
|
|
Config.
|
|
|
|
end_per_suite(_Config) ->
|
|
application:stop(meck).
|
|
|
|
init_per_group(git, Config) ->
|
|
[{deps_type, git} | Config];
|
|
init_per_group(pkg, Config) ->
|
|
[{deps_type, pkg} | Config];
|
|
init_per_group(_, Config) ->
|
|
Config.
|
|
|
|
end_per_group(_, Config) ->
|
|
Config.
|
|
|
|
init_per_testcase(Case, Config) ->
|
|
DepsType = ?config(deps_type, Config),
|
|
{Deps, Unlocks} = upgrades(Case),
|
|
Expanded = expand_deps(DepsType, Deps),
|
|
[{unlocks, normalize_unlocks(Unlocks)},
|
|
{mock, fun() -> mock_deps(DepsType, Expanded, []) end}
|
|
| setup_project(Case, Config, Expanded)].
|
|
|
|
end_per_testcase(_, Config) ->
|
|
meck:unload(),
|
|
Config.
|
|
|
|
setup_project(Case, Config0, Deps) ->
|
|
DepsType = ?config(deps_type, Config0),
|
|
Config = rebar_test_utils:init_rebar_state(
|
|
Config0,
|
|
atom_to_list(Case)++"_"++atom_to_list(DepsType)++"_"
|
|
),
|
|
AppDir = ?config(apps, Config),
|
|
rebar_test_utils:create_app(AppDir, "Root", "0.0.0", [kernel, stdlib]),
|
|
TopDeps = top_level_deps(Deps),
|
|
RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
|
|
[{rebarconfig, RebarConf} | Config].
|
|
|
|
|
|
upgrades(top) ->
|
|
{[{"A", [{"B", [{"D", "1", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% upgrade vs. locked after upgrade
|
|
[{"A", []},
|
|
{"B", {error, transitive_dependency}},
|
|
{"C", {error, transitive_dependency}},
|
|
{"D", "1", {error, transitive_dependency}},
|
|
{"D", "2", {error, unknown_dependency}}]};
|
|
upgrades(pair) ->
|
|
{[{"A", [{"C", []}]},
|
|
{"B", [{"D", []}]}],
|
|
[{"A", ["B"]},
|
|
{"B", ["A"]},
|
|
{"C", {error, transitive_dependency}},
|
|
{"D", {error, transitive_dependency}}]};
|
|
upgrades(triplet) ->
|
|
{[{"A", [{"D",[]},
|
|
{"E",[]}]},
|
|
{"B", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", [{"H",[]},
|
|
{"I",[]}]}],
|
|
[{"A", ["B","C"]},
|
|
{"B", ["A","C"]},
|
|
{"C", ["A","B"]},
|
|
{"D", {error, transitive_dependency}},
|
|
%% ...
|
|
{"I", {error, transitive_dependency}}]};
|
|
upgrades(tree) ->
|
|
{[{"A", [{"D",[{"J",[]}]},
|
|
{"E",[{"K",[]}]}]},
|
|
{"B", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", [{"H",[]},
|
|
{"I",[]}]}],
|
|
[{"A", ["B","C"]},
|
|
{"B", ["A","C"]},
|
|
{"C", ["A","B"]},
|
|
{"D", {error, transitive_dependency}},
|
|
%% ...
|
|
{"K", {error, transitive_dependency}}]}.
|
|
|
|
%% TODO: add a test that verifies that unlocking files and then
|
|
%% running the upgrade code is enough to properly upgrade things.
|
|
|
|
top_level_deps([]) -> [];
|
|
top_level_deps([{{Name, Vsn, Ref}, _} | Deps]) ->
|
|
[{list_to_atom(Name), Vsn, Ref} | top_level_deps(Deps)];
|
|
top_level_deps([{{pkg, Name, Vsn, _URL}, _} | Deps]) ->
|
|
[{list_to_atom(Name), Vsn} | top_level_deps(Deps)].
|
|
|
|
mock_deps(git, Deps, Upgrades) ->
|
|
mock_git_resource:mock([{deps, flat_deps(Deps)}, {upgrade, Upgrades}]);
|
|
mock_deps(pkg, Deps, Upgrades) ->
|
|
mock_pkg_resource:mock([{pkgdeps, flat_pkgdeps(Deps)}, {upgrade, Upgrades}]).
|
|
|
|
flat_deps([]) -> [];
|
|
flat_deps([{{Name,_Vsn,Ref}, Deps} | Rest]) ->
|
|
[{{Name,vsn_from_ref(Ref)}, top_level_deps(Deps)}]
|
|
++
|
|
flat_deps(Deps)
|
|
++
|
|
flat_deps(Rest).
|
|
|
|
vsn_from_ref({git, _, {_, Vsn}}) -> Vsn;
|
|
vsn_from_ref({git, _, Vsn}) -> Vsn.
|
|
|
|
flat_pkgdeps([]) -> [];
|
|
flat_pkgdeps([{{pkg, Name, Vsn, _Url}, Deps} | Rest]) ->
|
|
[{{iolist_to_binary(Name),iolist_to_binary(Vsn)}, top_level_deps(Deps)}]
|
|
++
|
|
flat_pkgdeps(Deps)
|
|
++
|
|
flat_pkgdeps(Rest).
|
|
|
|
expand_deps(_, []) -> [];
|
|
expand_deps(git, [{Name, Deps} | Rest]) ->
|
|
Dep = {Name, ".*", {git, "https://example.org/user/"++Name++".git", "master"}},
|
|
[{Dep, expand_deps(git, Deps)} | expand_deps(git, Rest)];
|
|
expand_deps(git, [{Name, Vsn, Deps} | Rest]) ->
|
|
Dep = {Name, Vsn, {git, "https://example.org/user/"++Name++".git", {tag, Vsn}}},
|
|
[{Dep, expand_deps(git, Deps)} | expand_deps(git, Rest)];
|
|
expand_deps(pkg, [{Name, Deps} | Rest]) ->
|
|
Dep = {pkg, Name, "0.0.0", "https://example.org/user/"++Name++".tar.gz"},
|
|
[{Dep, expand_deps(pkg, Deps)} | expand_deps(pkg, Rest)];
|
|
expand_deps(pkg, [{Name, Vsn, Deps} | Rest]) ->
|
|
Dep = {pkg, Name, Vsn, "https://example.org/user/"++Name++".tar.gz"},
|
|
[{Dep, expand_deps(pkg, Deps)} | expand_deps(pkg, Rest)].
|
|
|
|
normalize_unlocks([]) -> [];
|
|
normalize_unlocks([{App, Locks} | Rest]) ->
|
|
[{iolist_to_binary(App),
|
|
normalize_unlocks_expect(Locks)} | normalize_unlocks(Rest)];
|
|
normalize_unlocks([{App, Vsn, Locks} | Rest]) ->
|
|
[{iolist_to_binary(App), iolist_to_binary(Vsn),
|
|
normalize_unlocks_expect(Locks)} | normalize_unlocks(Rest)].
|
|
|
|
normalize_unlocks_expect({error, Reason}) ->
|
|
{error, Reason};
|
|
normalize_unlocks_expect([]) ->
|
|
[];
|
|
normalize_unlocks_expect([{App,Vsn} | Rest]) ->
|
|
[{iolist_to_binary(App), iolist_to_binary(Vsn)}
|
|
| normalize_unlocks_expect(Rest)];
|
|
normalize_unlocks_expect([App | Rest]) ->
|
|
[iolist_to_binary(App) | normalize_unlocks_expect(Rest)].
|
|
|
|
top(Config) -> run(Config).
|
|
pair(Config) -> run(Config).
|
|
triplet(Config) -> run(Config).
|
|
tree(Config) -> run(Config).
|
|
|
|
run(Config) ->
|
|
apply(?config(mock, Config), []),
|
|
{ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
|
|
%% Install dependencies before re-mocking for an upgrade
|
|
rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
|
|
Unlocks = ?config(unlocks, Config),
|
|
[begin
|
|
ct:pal("Unlocks: ~p -> ~p", [App, Unlocked]),
|
|
Expectation = case Unlocked of
|
|
Tuple when is_tuple(Tuple) -> Tuple;
|
|
_ -> {unlocked, Unlocked}
|
|
end,
|
|
rebar_test_utils:run_and_check(
|
|
Config, RebarConfig, ["upgrade", App], Expectation
|
|
)
|
|
end || {App, Unlocked} <- Unlocks].
|
|
|