summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/rebar_deps_SUITE.erl1
-rw-r--r--test/rebar_test_utils.erl12
-rw-r--r--test/rebar_upgrade_SUITE.erl185
3 files changed, 196 insertions, 2 deletions
diff --git a/test/rebar_deps_SUITE.erl b/test/rebar_deps_SUITE.erl
index d67efe4..8407b55 100644
--- a/test/rebar_deps_SUITE.erl
+++ b/test/rebar_deps_SUITE.erl
@@ -1,4 +1,3 @@
-%%% TODO: check that warnings are appearing
-module(rebar_deps_SUITE).
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl
index 6095d6d..af40995 100644
--- a/test/rebar_test_utils.erl
+++ b/test/rebar_test_utils.erl
@@ -53,7 +53,17 @@ run_and_check(Config, RebarConfig, Command, Expect) ->
?assertEqual({error, Reason}, Res);
{ok, Expected} ->
{ok, _} = Res,
- check_results(AppDir, Expected)
+ check_results(AppDir, Expected);
+ {unlocked, Expected} ->
+ ct:pal("Expected: ~p", [Expected]),
+ {ok, ResState} = Res,
+ Locks = rebar_state:lock(ResState),
+ ct:pal("Locks: ~p", [Locks]),
+ ?assertEqual(lists:sort(Expected),
+ lists:sort([rebar_app_info:name(Lock)
+ || Lock <- Locks]));
+ return ->
+ Res
end.
%% @doc Creates a dummy application including:
diff --git a/test/rebar_upgrade_SUITE.erl b/test/rebar_upgrade_SUITE.erl
new file mode 100644
index 0000000..5915d0d
--- /dev/null
+++ b/test/rebar_upgrade_SUITE.erl
@@ -0,0 +1,185 @@
+-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].
+