diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/rebar_deps_SUITE.erl | 1 | ||||
-rw-r--r-- | test/rebar_test_utils.erl | 12 | ||||
-rw-r--r-- | test/rebar_upgrade_SUITE.erl | 185 |
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]. + |