-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}, novsn_pkg].
|
|
|
|
groups() ->
|
|
[{all, [], [top_a, top_b, top_c, top_d1, top_d2, top_e,
|
|
pair_a, pair_b, pair_ab, pair_c, pair_all,
|
|
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,
|
|
profiles, profiles_exclusion]},
|
|
{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(novsn_pkg, Config0) ->
|
|
Config = rebar_test_utils:init_rebar_state(Config0, "novsn_pkg_"),
|
|
AppDir = ?config(apps, Config),
|
|
RebarConf = rebar_test_utils:create_config(AppDir, [{deps, [fakeapp]}]),
|
|
|
|
Deps = [{{<<"fakeapp">>, <<"1.0.0">>}, []}],
|
|
UpDeps = [{{<<"fakeapp">>, <<"1.1.0">>}, []}],
|
|
Upgrades = ["fakeapp"],
|
|
|
|
[{rebarconfig, RebarConf},
|
|
{mock, fun() ->
|
|
catch mock_pkg_resource:unmock(),
|
|
mock_pkg_resource:mock([{pkgdeps, Deps}, {upgrade, []}])
|
|
end},
|
|
{mock_update, fun() ->
|
|
catch mock_pkg_resource:unmock(),
|
|
mock_pkg_resource:mock([{pkgdeps, UpDeps++Deps}, {upgrade, Upgrades}])
|
|
end},
|
|
{expected, {ok, [{dep, "fakeapp", "1.1.0"}, {lock, "fakeapp", "1.1.0"}]}}
|
|
| Config];
|
|
init_per_testcase(Case, Config) ->
|
|
DepsType = ?config(deps_type, Config),
|
|
{Deps, UpDeps, ToUp, Expectations} = upgrades(Case),
|
|
Expanded = rebar_test_utils:expand_deps(DepsType, Deps),
|
|
UpExpanded = rebar_test_utils:expand_deps(DepsType, UpDeps),
|
|
[{expected, normalize_unlocks(Expectations)},
|
|
{mock, fun() -> mock_deps(DepsType, Expanded, []) end},
|
|
{mock_update, fun() -> mock_deps(DepsType, Expanded, UpExpanded, ToUp) end}
|
|
| setup_project(Case, Config, Expanded, UpExpanded)].
|
|
|
|
end_per_testcase(_, Config) ->
|
|
meck:unload(),
|
|
Config.
|
|
|
|
setup_project(Case=umbrella_config, Config0, Deps, UpDeps) ->
|
|
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]),
|
|
TopDeps = rebar_test_utils:top_level_deps(Deps),
|
|
TopConf = rebar_test_utils:create_config(AppDir, [{deps, []}]),
|
|
RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
|
|
[{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(
|
|
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 = rebar_test_utils:top_level_deps(Deps),
|
|
RebarConf = rebar_test_utils:create_config(AppDir, [{deps, TopDeps}]),
|
|
[{rebarconfig, RebarConf},
|
|
{next_top_deps, rebar_test_utils:top_level_deps(UpDeps)} | Config].
|
|
|
|
|
|
upgrades(top_a) ->
|
|
%% Original tree
|
|
{[{"A", "1", [{"B", [{"D", "1", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Updated tree
|
|
[{"A", "1", [{"B", [{"D", "3", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Modified apps, gobally
|
|
["A","B","D"],
|
|
%% upgrade vs. new tree
|
|
{"A", [{"A","1"}, "B", "C", {"D","3"}]}};
|
|
upgrades(top_b) ->
|
|
%% Original tree
|
|
{[{"A", "1", [{"B", [{"D", "1", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Updated tree
|
|
[{"A", "1", [{"B", [{"D", "3", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Modified apps, gobally
|
|
["A","B","D"],
|
|
%% upgrade vs. new tree
|
|
{"B", {error, {rebar_prv_upgrade, {transitive_dependency, <<"B">>}}}}};
|
|
upgrades(top_c) ->
|
|
%% Original tree
|
|
{[{"A", "1", [{"B", [{"D", "1", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Updated tree
|
|
[{"A", "1", [{"B", [{"D", "3", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Modified apps, gobally
|
|
["A","B","D"],
|
|
%% upgrade vs. new tree
|
|
{"C", {error, {rebar_prv_upgrade, {transitive_dependency, <<"C">>}}}}};
|
|
upgrades(top_d1) ->
|
|
%% Original tree
|
|
{[{"A", "1", [{"B", [{"D", "1", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Updated tree
|
|
[{"A", "1", [{"B", [{"D", "3", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Modified apps, gobally
|
|
["A","B","D"],
|
|
%% upgrade vs. new tree
|
|
{"D", {error, {rebar_prv_upgrade, {transitive_dependency, <<"D">>}}}}};
|
|
upgrades(top_d2) ->
|
|
%% Original tree
|
|
{[{"A", "1", [{"B", [{"D", "1", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Updated tree
|
|
[{"A", "1", [{"B", [{"D", "3", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Modified apps, gobally
|
|
["A","B","D"],
|
|
%% upgrade vs. new tree
|
|
{"D", {error, {rebar_prv_upgrade, {transitive_dependency, <<"D">>}}}}};
|
|
upgrades(top_e) ->
|
|
%% Original tree
|
|
{[{"A", "1", [{"B", [{"D", "1", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Updated tree
|
|
[{"A", "1", [{"B", [{"D", "3", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
%% Modified apps, gobally
|
|
["A","B","D"],
|
|
%% upgrade vs. new tree
|
|
{"E", {error, {rebar_prv_upgrade, {unknown_dependency, <<"E">>}}}}};
|
|
upgrades(pair_a) ->
|
|
{[{"A", "1", [{"C", "1", []}]},
|
|
{"B", "1", [{"D", "1", []}]}
|
|
],
|
|
[{"A", "2", [{"C", "2", []}]},
|
|
{"B", "2", [{"D", "2", []}]}
|
|
],
|
|
["A","B","C","D"],
|
|
{"A", [{"A","2"},{"C","2"},{"B","1"},{"D","1"}]}};
|
|
upgrades(pair_b) ->
|
|
{[{"A", "1", [{"C", "1", []}]},
|
|
{"B", "1", [{"D", "1", []}]}
|
|
],
|
|
[{"A", "2", [{"C", "2", []}]},
|
|
{"B", "2", [{"D", "2", []}]}
|
|
],
|
|
["A","B","C","D"],
|
|
{"B", [{"A","1"},{"C","1"},{"B","2"},{"D","2"}]}};
|
|
upgrades(pair_ab) ->
|
|
{[{"A", "1", [{"C", "1", []}]},
|
|
{"B", "1", [{"D", "1", []}]}
|
|
],
|
|
[{"A", "2", [{"C", "2", []}]},
|
|
{"B", "2", [{"D", "2", []}]}
|
|
],
|
|
["A","B","C","D"],
|
|
{"A,B", [{"A","2"},{"C","2"},{"B","2"},{"D","2"}]}};
|
|
upgrades(pair_c) ->
|
|
{[{"A", "1", [{"C", "1", []}]},
|
|
{"B", "1", [{"D", "1", []}]}
|
|
],
|
|
[{"A", "2", [{"C", "2", []}]},
|
|
{"B", "2", [{"D", "2", []}]}
|
|
],
|
|
["A","B","C","D"],
|
|
{"C", {error, {rebar_prv_upgrade, {transitive_dependency, <<"C">>}}}}};
|
|
upgrades(pair_all) ->
|
|
{[{"A", "1", [{"C", "1", []}]},
|
|
{"B", "1", [{"D", "1", []}]}
|
|
],
|
|
[{"A", "2", [{"C", "2", []}]},
|
|
{"B", "2", [{"D", "2", []}]}
|
|
],
|
|
["A","B","C","D"],
|
|
{"", [{"A","2"},{"C","2"},{"B","2"},{"D","2"}]}};
|
|
upgrades(triplet_a) ->
|
|
{[{"A", "1", [{"D",[]},
|
|
{"E","3",[]}]},
|
|
{"B", "1", [{"F","1",[]},
|
|
{"G",[]}]},
|
|
{"C", "0", [{"H","3",[]},
|
|
{"I",[]}]}],
|
|
[{"A", "1", [{"D",[]},
|
|
{"E","2",[]}]},
|
|
{"B", "1", [{"F","1",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H","4",[]},
|
|
{"I",[]}]}],
|
|
["A","C","E","H"],
|
|
{"A", [{"A","1"}, "D", {"E","2"},
|
|
{"B","1"}, {"F","1"}, "G",
|
|
{"C","0"}, {"H","3"}, "I"]}};
|
|
upgrades(triplet_b) ->
|
|
{[{"A", "1", [{"D",[]},
|
|
{"E","3",[]}]},
|
|
{"B", "1", [{"F","1",[]},
|
|
{"G",[]}]},
|
|
{"C", "0", [{"H","3",[]},
|
|
{"I",[]}]}],
|
|
[{"A", "2", [{"D",[]},
|
|
{"E","2",[]}]},
|
|
{"B", "1", [{"F","1",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H","4",[]},
|
|
{"I",[]}]}],
|
|
["A","C","E","H"],
|
|
{"B", [{"A","1"}, "D", {"E","3"},
|
|
{"B","1"}, {"F","1"}, "G",
|
|
{"C","0"}, {"H","3"}, "I"]}};
|
|
upgrades(triplet_c) ->
|
|
{[{"A", "1", [{"D",[]},
|
|
{"E","3",[]}]},
|
|
{"B", "1", [{"F","1",[]},
|
|
{"G",[]}]},
|
|
{"C", "0", [{"H","3",[]},
|
|
{"I",[]}]}],
|
|
[{"A", "2", [{"D",[]},
|
|
{"E","2",[]}]},
|
|
{"B", "1", [{"F","1",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H","4",[]},
|
|
{"I",[]}]}],
|
|
["A","C","E","H"],
|
|
{"C", [{"A","1"}, "D", {"E","3"},
|
|
{"B","1"}, {"F","1"}, "G",
|
|
{"C","1"}, {"H","4"}, "I"]}};
|
|
upgrades(tree_a) ->
|
|
{[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","2",[]}]}
|
|
],
|
|
[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "2", [{"H",[]}]}
|
|
],
|
|
["C"],
|
|
{"A", [{"A","1"}, "D", "J", "E",
|
|
{"B","1"}, "F", "G",
|
|
{"C","1"}, "H", {"I","2"}]}};
|
|
upgrades(tree_b) ->
|
|
{[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","2",[]}]}
|
|
],
|
|
[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "2", [{"H",[]}]}
|
|
],
|
|
["C"],
|
|
{"B", [{"A","1"}, "D", "J", "E",
|
|
{"B","1"}, "F", "G",
|
|
{"C","1"}, "H", {"I","2"}]}};
|
|
upgrades(tree_c) ->
|
|
{[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","2",[]}]}
|
|
],
|
|
[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]}]}
|
|
],
|
|
["C","I"],
|
|
{"C", [{"A","1"}, "D", "J", "E", {"I","1"},
|
|
{"B","1"}, "F", "G",
|
|
{"C","1"}, "H"]}};
|
|
upgrades(tree_c2) ->
|
|
{[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","2",[]}]}
|
|
],
|
|
[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[{"K",[]}]},
|
|
{"I","2",[]}]}
|
|
],
|
|
["C", "H"],
|
|
{"C", [{"A","1"}, "D", "J", "E",
|
|
{"B","1"}, "F", "G",
|
|
{"C","1"}, "H", {"I", "2"}, "K"]}};
|
|
upgrades(tree_cj) ->
|
|
{[{"A", "1", [{"D",[{"J", "1",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","1",[]}]}
|
|
],
|
|
[{"A", "1", [{"D",[{"J", "2", []}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","1",[]}]}
|
|
],
|
|
["C","J"],
|
|
{"C", [{"A","1"}, "D", {"J", "1"}, "E", {"I","1"},
|
|
{"B","1"}, "F", "G",
|
|
{"C","1"}, "H"]}};
|
|
upgrades(tree_ac) ->
|
|
{[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","2",[]}]}
|
|
],
|
|
[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]}]}
|
|
],
|
|
["C","I"],
|
|
{"C, A", [{"A","1"}, "D", "J", "E", {"I","1"},
|
|
{"B","1"}, "F", "G",
|
|
{"C","1"}, "H"]}};
|
|
upgrades(tree_all) ->
|
|
{[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","2",[]}]}
|
|
],
|
|
[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]}]}
|
|
],
|
|
["C","I"],
|
|
{"", [{"A","1"}, "D", "J", "E", {"I","1"},
|
|
{"B","1"}, "F", "G",
|
|
{"C","1"}, "H"]}};
|
|
upgrades(delete_d) ->
|
|
{[{"A", "1", [{"B", [{"D", "1", []}]},
|
|
{"C", [{"D", "2", []}]}]}
|
|
],
|
|
[{"A", "2", [{"B", []},
|
|
{"C", []}]}
|
|
],
|
|
["A","B", "C"],
|
|
%% upgrade vs. new tree
|
|
{"", [{"A","2"}, "B", "C"]}};
|
|
upgrades(promote) ->
|
|
{[{"A", "1", [{"C", "1", []}]},
|
|
{"B", "1", [{"D", "1", []}]}
|
|
],
|
|
[{"A", "2", [{"C", "2", []}]},
|
|
{"B", "2", [{"D", "2", []}]},
|
|
{"C", "3", []}
|
|
],
|
|
["A","B","C","D"],
|
|
{"C", [{"A","1"},{"C","3"},{"B","1"},{"D","1"}]}};
|
|
upgrades(stable_lock) ->
|
|
{[{"A", "1", [{"C", "1", []}]},
|
|
{"B", "1", [{"D", "1", []}]}
|
|
], % lock after this
|
|
[{"A", "2", [{"C", "2", []}]},
|
|
{"B", "2", [{"D", "2", []}]}
|
|
],
|
|
[],
|
|
%% Run a regular lock and no app should be upgraded
|
|
{"any", [{"A","1"},{"C","1"},{"B","1"},{"D","1"}]}};
|
|
upgrades(fwd_lock) ->
|
|
{[{"A", "1", [{"C", "1", []}]},
|
|
{"B", "1", [{"D", "1", []}]}
|
|
],
|
|
[{"A", "2", [{"C", "2", []}]},
|
|
{"B", "2", [{"D", "2", []}]}
|
|
],
|
|
["A","B","C","D"],
|
|
%% For this one, we should build, rewrite the lock
|
|
%% file to include the result post-upgrade, and then
|
|
%% run a regular lock to see that the lock file is respected
|
|
%% in deps.
|
|
{"any", [{"A","2"},{"C","2"},{"B","2"},{"D","2"}]}};
|
|
upgrades(compile_upgrade_parity) ->
|
|
{[{"A", "1", [{"D",[{"J",[]}]},
|
|
{"E",[{"I","1",[]}]}]},
|
|
{"B", "1", [{"F",[]},
|
|
{"G",[]}]},
|
|
{"C", "1", [{"H",[]},
|
|
{"I","2",[]}]}
|
|
],
|
|
[],
|
|
[],
|
|
{"", [{"A","1"}, "D", "J", "E", {"I","1"},
|
|
{"B","1"}, "F", "G",
|
|
{"C","1"}, "H"]}};
|
|
upgrades(umbrella_config) ->
|
|
{[{"A", "1", []}],
|
|
[{"A", "2", []}],
|
|
["A"],
|
|
{"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.
|
|
|
|
mock_deps(git, Deps, Upgrades) ->
|
|
catch mock_git_resource:unmock(),
|
|
{SrcDeps, _} = rebar_test_utils:flat_deps(Deps),
|
|
mock_git_resource:mock([{deps, SrcDeps}, {upgrade, Upgrades}]);
|
|
mock_deps(pkg, Deps, Upgrades) ->
|
|
catch mock_pkg_resource:unmock(),
|
|
{_, PkgDeps} = rebar_test_utils:flat_deps(Deps),
|
|
mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]).
|
|
|
|
mock_deps(git, OldDeps, Deps, Upgrades) ->
|
|
catch mock_git_resource:unmock(),
|
|
{SrcDeps, _} = rebar_test_utils:flat_deps(Deps++OldDeps),
|
|
mock_git_resource:mock([{deps, SrcDeps}, {upgrade, Upgrades}]);
|
|
mock_deps(pkg, OldDeps, Deps, Upgrades) ->
|
|
catch mock_pkg_resource:unmock(),
|
|
{_, PkgDeps} = rebar_test_utils:flat_deps(Deps++OldDeps),
|
|
mock_pkg_resource:mock([{pkgdeps, PkgDeps}, {upgrade, Upgrades}]).
|
|
|
|
normalize_unlocks({App, Locks}) ->
|
|
{iolist_to_binary(App),
|
|
normalize_unlocks_expect(Locks)};
|
|
normalize_unlocks({App, Vsn, Locks}) ->
|
|
{iolist_to_binary(App), iolist_to_binary(Vsn),
|
|
normalize_unlocks_expect(Locks)}.
|
|
|
|
normalize_unlocks_expect({error, Reason}) ->
|
|
{error, Reason};
|
|
normalize_unlocks_expect([]) ->
|
|
[];
|
|
normalize_unlocks_expect([{App,Vsn} | Rest]) ->
|
|
[{dep, App, Vsn},
|
|
{lock, App, Vsn}
|
|
| normalize_unlocks_expect(Rest)];
|
|
normalize_unlocks_expect([App | Rest]) ->
|
|
[{dep, App},
|
|
{lock, App} | normalize_unlocks_expect(Rest)].
|
|
|
|
top_a(Config) -> run(Config).
|
|
top_b(Config) -> run(Config).
|
|
top_c(Config) -> run(Config).
|
|
top_d1(Config) -> run(Config).
|
|
top_d2(Config) -> run(Config).
|
|
top_e(Config) -> run(Config).
|
|
|
|
pair_a(Config) -> run(Config).
|
|
pair_b(Config) -> run(Config).
|
|
pair_ab(Config) -> run(Config).
|
|
pair_c(Config) -> run(Config).
|
|
pair_all(Config) -> run(Config).
|
|
|
|
triplet_a(Config) -> run(Config).
|
|
triplet_b(Config) -> run(Config).
|
|
triplet_c(Config) -> run(Config).
|
|
|
|
tree_a(Config) -> run(Config).
|
|
tree_b(Config) -> run(Config).
|
|
tree_c(Config) -> run(Config).
|
|
tree_c2(Config) -> run(Config).
|
|
tree_cj(Config) -> run(Config).
|
|
tree_ac(Config) -> run(Config).
|
|
tree_all(Config) -> run(Config).
|
|
promote(Config) -> run(Config).
|
|
|
|
delete_d(Config) ->
|
|
meck:new(rebar_log, [no_link, passthrough]),
|
|
run(Config),
|
|
Infos = [{Str, Args}
|
|
|| {_, {rebar_log, log, [info, Str, Args]}, _} <- meck:history(rebar_log)],
|
|
meck:unload(rebar_log),
|
|
?assertNotEqual([],
|
|
[1 || {"App ~ts is no longer needed and can be deleted.",
|
|
[<<"D">>]} <- Infos]).
|
|
|
|
stable_lock(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, []}),
|
|
{App, Unlocks} = ?config(expected, Config),
|
|
ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
|
|
Expectation = case Unlocks of
|
|
{error, Term} -> {error, Term};
|
|
_ -> {ok, Unlocks}
|
|
end,
|
|
apply(?config(mock_update, Config), []),
|
|
NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
|
|
[{deps, ?config(next_top_deps, Config)}]),
|
|
{ok, NewRebarConfig} = file:consult(NewRebarConf),
|
|
rebar_test_utils:run_and_check(
|
|
Config, NewRebarConfig, ["lock", App], Expectation
|
|
).
|
|
|
|
fwd_lock(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, []}),
|
|
{App, Unlocks} = ?config(expected, Config),
|
|
ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
|
|
Expectation = case Unlocks of
|
|
{error, Term} -> {error, Term};
|
|
_ -> {ok, Unlocks}
|
|
end,
|
|
rewrite_locks(Expectation, Config),
|
|
apply(?config(mock_update, Config), []),
|
|
NewRebarConf = rebar_test_utils:create_config(?config(apps, Config),
|
|
[{deps, ?config(next_top_deps, Config)}]),
|
|
{ok, NewRebarConfig} = file:consult(NewRebarConf),
|
|
rebar_test_utils:run_and_check(
|
|
Config, NewRebarConfig, ["lock", App], Expectation
|
|
).
|
|
|
|
compile_upgrade_parity(Config) ->
|
|
AppDir = ?config(apps, Config),
|
|
apply(?config(mock, Config), []),
|
|
{ok, RebarConfig} = file:consult(?config(rebarconfig, Config)),
|
|
%% compiling and upgrading should generate the same lockfiles when
|
|
%% deps are identical
|
|
Lockfile = filename:join([AppDir, "rebar.lock"]),
|
|
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}),
|
|
{ok, CompileLockData1} = file:read_file(Lockfile),
|
|
rebar_test_utils:run_and_check(Config, RebarConfig, ["upgrade"], {ok, []}),
|
|
{ok, UpgradeLockData} = file:read_file(Lockfile),
|
|
rebar_test_utils:run_and_check(Config, RebarConfig, ["compile"], {ok, []}),
|
|
{ok, CompileLockData2} = file:read_file(Lockfile),
|
|
?assertEqual(CompileLockData1, CompileLockData2),
|
|
?assertEqual(CompileLockData1, UpgradeLockData).
|
|
|
|
umbrella_config(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, []}),
|
|
{App, Unlocks} = ?config(expected, Config),
|
|
ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
|
|
Expectation = case Unlocks of
|
|
{error, Term} -> {error, Term};
|
|
_ -> {ok, Unlocks}
|
|
end,
|
|
|
|
meck:new(rebar_prv_upgrade, [passthrough]),
|
|
meck:expect(rebar_prv_upgrade, do, fun(S) ->
|
|
apply(?config(mock_update, Config), []),
|
|
meck:passthrough([S])
|
|
end),
|
|
_NewRebarConf = rebar_test_utils:create_config(filename:dirname(?config(rebarumbrella, Config)),
|
|
[{deps, ?config(next_top_deps, Config)}]),
|
|
%% re-run from the top-level with the old config still in place;
|
|
%% detection must happen when going for umbrella apps!
|
|
rebar_test_utils:run_and_check(
|
|
Config, TopConfig, ["upgrade", App], Expectation
|
|
),
|
|
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),
|
|
{ok, RebarConfig} = file:consult(ConfigPath),
|
|
%% Install dependencies before re-mocking for an upgrade
|
|
rebar_test_utils:run_and_check(Config, RebarConfig, ["lock"], {ok, []}),
|
|
{App, Unlocks} = ?config(expected, Config),
|
|
ct:pal("Upgrades: ~p -> ~p", [App, Unlocks]),
|
|
Expectation = case Unlocks of
|
|
{error, Term} -> {error, Term};
|
|
_ -> {ok, Unlocks}
|
|
end,
|
|
|
|
meck:new(rebar_prv_upgrade, [passthrough]),
|
|
meck:expect(rebar_prv_upgrade, do, fun(S) ->
|
|
apply(?config(mock_update, Config), []),
|
|
meck:passthrough([S])
|
|
end),
|
|
NewRebarConf = rebar_test_utils:create_config(filename:dirname(ConfigPath),
|
|
[{deps, ?config(next_top_deps, Config)}]),
|
|
{ok, NewRebarConfig} = file:consult(NewRebarConf),
|
|
rebar_test_utils:run_and_check(
|
|
Config, NewRebarConfig, ["upgrade", App], Expectation
|
|
),
|
|
meck:unload(rebar_prv_upgrade).
|
|
|
|
novsn_pkg(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, []}),
|
|
Expectation = ?config(expected, Config),
|
|
apply(?config(mock_update, Config), []),
|
|
rebar_test_utils:run_and_check(
|
|
Config, RebarConfig, ["upgrade"], Expectation
|
|
),
|
|
ok.
|
|
|
|
rewrite_locks({ok, Expectations}, Config) ->
|
|
AppDir = ?config(apps, Config),
|
|
LockFile = filename:join([AppDir, "rebar.lock"]),
|
|
Locks = case ?config(deps_type, Config) of
|
|
git ->
|
|
{ok, [LockData]} = file:consult(LockFile),
|
|
LockData;
|
|
pkg ->
|
|
{ok, [{_Vsn, LockData}|_]} = file:consult(LockFile),
|
|
LockData
|
|
end,
|
|
ExpLocks = [{list_to_binary(Name), Vsn}
|
|
|| {lock, Name, Vsn} <- Expectations],
|
|
NewLocks = lists:foldl(
|
|
fun({App, {pkg, Name, _}, Lvl}, Acc) ->
|
|
Vsn = list_to_binary(proplists:get_value(App,ExpLocks)),
|
|
[{App, {pkg, Name, Vsn}, Lvl} | Acc]
|
|
; ({App, {git, URL, {ref, _}}, Lvl}, Acc) ->
|
|
Vsn = proplists:get_value(App,ExpLocks),
|
|
[{App, {git, URL, {ref, Vsn}}, Lvl} | Acc]
|
|
end, [], Locks),
|
|
ct:pal("rewriting locks from ~p to~n~p", [Locks, NewLocks]),
|
|
file:write_file(LockFile, io_lib:format("~p.~n", [NewLocks])).
|