-module(rebar_plugins_SUITE). -export([suite/0, init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, all/0, compile_plugins/1, compile_global_plugins/1, complex_plugins/1, list/1, upgrade/1, upgrade_project_plugin/1, upgrade_no_args/1, sub_app_plugins/1, sub_app_plugin_overrides/1, project_plugins/1, use_checkout_plugins/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). -include_lib("kernel/include/file.hrl"). suite() -> []. init_per_suite(Config) -> Config. end_per_suite(_Config) -> ok. init_per_testcase(_, Config) -> rebar_test_utils:init_rebar_state(Config). end_per_testcase(_, _Config) -> catch meck:unload(). all() -> [compile_plugins, compile_global_plugins, complex_plugins, list, upgrade, upgrade_project_plugin, sub_app_plugins, sub_app_plugin_overrides, project_plugins, use_checkout_plugins]. %% Tests that compiling a project installs and compiles the plugins of deps compile_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), Plugins = rebar_test_utils:expand_deps(git, [{PluginName, Vsn, []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Plugins), mock_git_resource:mock([{deps, SrcDeps}]), mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(DepName), list_to_binary(Vsn)}, []}]}, {config, [{plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}}]}]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ list_to_atom(DepName) ]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {plugin, PluginName}, {dep, DepName}]} ). %% Tests that compiling a project installs and compiles the global plugins compile_global_plugins(Config) -> AppDir = ?config(apps, Config), GlobalDir = filename:join(AppDir, "global"), GlobalConfigDir = filename:join([GlobalDir, ".config", "rebar3"]), GlobalConfig = filename:join([GlobalDir, ".config", "rebar3", "rebar.config"]), meck:new(rebar_dir, [passthrough]), meck:expect(rebar_dir, global_config, fun() -> GlobalConfig end), meck:expect(rebar_dir, global_cache_dir, fun(_) -> GlobalDir end), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), mock_git_resource:mock([{deps, [{list_to_atom(PluginName), Vsn}, {list_to_atom(PluginName), Vsn2}, {{iolist_to_binary(DepName), iolist_to_binary(Vsn)}, []}]}]), rebar_test_utils:create_config(GlobalConfigDir, [{plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}} ]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}} ]}, {plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn2}}} ]}]), {ok, RConf} = file:consult(RConfFile), %% Runs global plugin install rebar3:init_config(), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {global_plugin, PluginName, Vsn}, {plugin, PluginName, Vsn2}, {dep, DepName}]} ), meck:unload(rebar_dir). %% Tests installing of plugin with transitive deps complex_plugins(Config) -> AppDir = ?config(apps, Config), meck:new(rebar_dir, [passthrough]), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), Vsn2 = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), DepName2 = rebar_test_utils:create_random_name("dep2_"), DepName3 = rebar_test_utils:create_random_name("dep3_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), Deps = rebar_test_utils:expand_deps(git, [{PluginName, Vsn2, [{DepName2, Vsn, [{DepName3, Vsn, []}]}]} ,{DepName, Vsn, []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ {list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn}}} ]}, {plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn2}}} ]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {plugin, PluginName, Vsn2}, {plugin, DepName2}, {plugin, DepName3}, {dep, DepName}]} ), meck:unload(rebar_dir). list(Config) -> rebar_test_utils:run_and_check( Config, [], ["plugins", "list"], {ok, []} ). upgrade(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]} ]), %% beam file to verify plugin is actually compiled PluginBeam = filename:join([AppDir, "_build", "default", "plugins", PkgName, "ebin", [PkgName, ".beam"]]), RConfFile = rebar_test_utils:create_config(AppDir, [{plugins, [list_to_atom(PkgName)]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name, valid}, {file, PluginBeam}, {plugin, PkgName, <<"0.1.1">>}]} ), catch mock_pkg_resource:unmock(), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.3">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]}, {upgrade, [PkgName]} ]), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["plugins", "upgrade", PkgName], {ok, [{app, Name, valid}, {file, PluginBeam}, {plugin, PkgName, <<"0.1.3">>}]} ), rebar_test_utils:run_and_check( Config, RConf, ["plugins", "upgrade", "--all"], {ok, [{app, Name, valid}, {file, PluginBeam}, {plugin, PkgName}]} ). upgrade_project_plugin(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), PkgName = rebar_test_utils:create_random_name("pkg1_"), mock_git_resource:mock([]), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]} ]), RConfFile = rebar_test_utils:create_config(AppDir, [{project_plugins, [list_to_atom(PkgName)]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {plugin, PkgName, <<"0.1.1">>}]} ), catch mock_pkg_resource:unmock(), mock_pkg_resource:mock([ {pkgdeps, [{{iolist_to_binary(PkgName), <<"0.1.0">>}, []}, {{iolist_to_binary(PkgName), <<"0.0.1">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.3">>}, []}, {{iolist_to_binary(PkgName), <<"0.1.1">>}, []}]}, {upgrade, [PkgName]} ]), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["plugins", "upgrade", PkgName], {ok, [{app, Name}, {plugin, PkgName, <<"0.1.3">>}]} ). upgrade_no_args(Config) -> try rebar_test_utils:run_and_check(Config, [], ["plugins", "upgrade"], return) catch {error, {rebar_prv_plugins_upgrade, no_arg}} -> ok end, ok. sub_app_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("sub_app1_"), Vsn = rebar_test_utils:create_random_vsn(), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(DepName), list_to_binary(Vsn)}, []}, {{list_to_binary(PluginName), list_to_binary(Vsn)}, []}]}]), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), rebar_test_utils:create_config(SubAppsDir, [{deps, [{list_to_binary(DepName), list_to_binary(Vsn)}]}, {plugins, [list_to_atom(PluginName)]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ list_to_atom(DepName) ]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, DepName}, {plugin, PluginName}]} ). %% Tests that overrides in a dep that includes a plugin are applied to plugin fetching sub_app_plugin_overrides(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("sub_app1_"), Vsn = rebar_test_utils:create_random_vsn(), Dep2Name = rebar_test_utils:create_random_name("dep2_"), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = rebar_test_utils:create_random_name("plugin1_"), Vsn2 = rebar_test_utils:create_random_vsn(), Deps = rebar_test_utils:expand_deps(git, [{PluginName, Vsn, [{DepName, Vsn, []}]}, {DepName, Vsn, []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Deps), mock_git_resource:mock([{deps, SrcDeps}]), mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(Dep2Name), list_to_binary(Vsn)}, []}]}, {config, [{plugins, [{list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}}]}, %% Dep2 overrides the plugin's deps to have vsn2 of dep1 {overrides, [{override, list_to_atom(PluginName), [{deps, [{list_to_atom(DepName), {git, "http://site.com/user/"++DepName++".git", {tag, Vsn2}}}]}]}]}]}]), SubAppsDir = filename:join([AppDir, "apps", Name]), rebar_test_utils:create_app(SubAppsDir, Name, Vsn, [kernel, stdlib]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [{list_to_binary(Dep2Name), list_to_binary(Vsn)}]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {dep, Dep2Name, Vsn}, {plugin, DepName, Vsn2}, {plugin, PluginName}]} ). %% Check that project plugins are first in providers even if they override defaults but that %% normal plugins do not project_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), DepName = rebar_test_utils:create_random_name("dep1_"), PluginName = "compile_plugin", PluginName2 = "release", Plugins = rebar_test_utils:expand_deps(git, [{PluginName, Vsn, []}, {PluginName2, Vsn, []}]), {SrcDeps, _} = rebar_test_utils:flat_deps(Plugins), mock_git_resource:mock([{deps, SrcDeps}], create_plugin), mock_pkg_resource:mock([{pkgdeps, [{{list_to_binary(DepName), list_to_binary(Vsn)}, []}]}, {config, [{plugins, [ {list_to_atom(PluginName), {git, "http://site.com/user/"++PluginName++".git", {tag, Vsn}}}]}]}]), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, [ list_to_atom(DepName) ]}, {project_plugins, [ {list_to_atom(PluginName2), {git, "http://site.com/user/"++PluginName2++".git", {tag, Vsn}}}]}]), {ok, RConf} = file:consult(RConfFile), %% Build with deps. {ok, State} = rebar_test_utils:run_and_check( Config, RConf, ["compile"], {ok, [{app, Name}, {plugin, PluginName}, {plugin, PluginName2}, {dep, DepName}]} ), %% Should have 2 release providers but only 1 compile provider Release = [P || P <- rebar_state:providers(State), providers:impl(P) =:= release, providers:namespace(P) =:= default], Compile = [P || P <- rebar_state:providers(State), providers:impl(P) =:= compile, providers:namespace(P) =:= default], ?assertEqual(length(Release), 2), ?assertEqual(length(Compile), 1). use_checkout_plugins(Config) -> AppDir = ?config(apps, Config), Name = rebar_test_utils:create_random_name("app1_"), Vsn = rebar_test_utils:create_random_vsn(), rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), PluginName = "checkedout", CheckoutsDir = filename:join(AppDir, "_checkouts/checkedout"), rebar_test_utils:create_plugin(CheckoutsDir, PluginName, "1.0.0", []), RConfFile = rebar_test_utils:create_config(AppDir, [{deps, []}, {plugins, [list_to_atom(PluginName)]}]), {ok, RConf} = file:consult(RConfFile), %% Verify we can run the plugin ?assertMatch({ok, _}, rebar_test_utils:run_and_check( Config, RConf, ["checkedout"], {ok, []} )).