summaryrefslogtreecommitdiff
path: root/test/rebar_test_utils.erl
diff options
context:
space:
mode:
Diffstat (limited to 'test/rebar_test_utils.erl')
-rw-r--r--test/rebar_test_utils.erl138
1 files changed, 138 insertions, 0 deletions
diff --git a/test/rebar_test_utils.erl b/test/rebar_test_utils.erl
new file mode 100644
index 0000000..08834f7
--- /dev/null
+++ b/test/rebar_test_utils.erl
@@ -0,0 +1,138 @@
+-module(rebar_test_utils).
+-include_lib("common_test/include/ct.hrl").
+-include_lib("eunit/include/eunit.hrl").
+-export([init_rebar_state/1, init_rebar_state/2, run_and_check/4]).
+-export([create_app/4, create_empty_app/4, create_config/2]).
+-export([create_random_name/1, create_random_vsn/0]).
+
+%%%%%%%%%%%%%%
+%%% Public %%%
+%%%%%%%%%%%%%%
+
+%% @doc {@see init_rebar_state/2}
+init_rebar_state(Config) -> init_rebar_state(Config, "apps_dir1_").
+
+%% @doc Takes a common test config and a name (string) and sets up
+%% a basic OTP app directory with a pre-configured rebar state to
+%% run tests with.
+init_rebar_state(Config, Name) ->
+ application:load(rebar),
+ DataDir = ?config(priv_dir, Config),
+ AppsDir = filename:join([DataDir, create_random_name(Name)]),
+ ok = ec_file:mkdir_p(AppsDir),
+ Verbosity = rebar3:log_level(),
+ rebar_log:init(command_line, Verbosity),
+ State = rebar_state:new([{base_dir, filename:join([AppsDir, "_build"])}]),
+ [{apps, AppsDir}, {state, State} | Config].
+
+%% @doc Takes common test config, a rebar config ([] if empty), a command to
+%% run ("install_deps", "compile", etc.), and a list of expected applications
+%% and/or dependencies to be present, and verifies whether they are all in
+%% place.
+%%
+%% The expectation list takes elements of the form:
+%% - `{app, Name :: string()}': checks that the app is properly built.
+%% - `{dep, Name :: string()}': checks that the dependency has been fetched.
+%% Ignores the build status of the dependency.
+%% - `{dep, Name :: string(), Vsn :: string()}': checks that the dependency
+%% has been fetched, and that a given version has been chosen. Useful to
+%% test for conflict resolution. Also ignores the build status of the
+%% dependency.
+%%
+%% This function assumes `init_rebar_state/1-2' has run before, in order to
+%% fetch the `apps' and `state' values from the CT config.
+run_and_check(Config, RebarConfig, Command, Expect) ->
+ %% Assumes init_rebar_state has run first
+ AppDir = ?config(apps, Config),
+ State = ?config(state, Config),
+ {ok,_} = rebar3:run(rebar_state:new(State, RebarConfig, AppDir), Command),
+ BuildDir = filename:join([AppDir, "_build", "default", "lib"]),
+ Deps = rebar_app_discover:find_apps([BuildDir], all),
+ DepsNames = [{ec_cnv:to_list(rebar_app_info:name(App)), App} || App <- Deps],
+ lists:foreach(
+ fun({app, Name}) ->
+ [App] = rebar_app_discover:find_apps([AppDir]),
+ ct:pal("Name: ~p", [Name]),
+ ?assertEqual(Name, ec_cnv:to_list(rebar_app_info:name(App)))
+ ; ({dep, Name}) ->
+ ct:pal("Name: ~p", [Name]),
+ ?assertNotEqual(false, lists:keyfind(Name, 1, DepsNames))
+ ; ({dep, Name, Vsn}) ->
+ ct:pal("Name: ~p, Vsn: ~p", [Name, Vsn]),
+ case lists:keyfind(Name, 1, DepsNames) of
+ false ->
+ error({app_not_found, Name});
+ {Name, App} ->
+ ?assertEqual(Vsn, rebar_app_info:original_vsn(App))
+ end
+ end, Expect).
+
+%% @doc Creates a dummy application including:
+%% - src/<file>.erl
+%% - src/<file>.app.src
+%% And returns a `rebar_app_info' object.
+create_app(AppDir, Name, Vsn, Deps) ->
+ write_src_file(AppDir, Name),
+ write_app_src_file(AppDir, Name, Vsn, Deps),
+ rebar_app_info:new(Name, Vsn, AppDir, Deps).
+
+%% @doc Creates a dummy application including:
+%% - ebin/<file>.app
+%% And returns a `rebar_app_info' object.
+create_empty_app(AppDir, Name, Vsn, Deps) ->
+ write_app_file(AppDir, Name, Vsn, Deps),
+ rebar_app_info:new(Name, Vsn, AppDir, Deps).
+
+%% @doc Creates a rebar.config file. The function accepts a list of terms,
+%% each of which will be dumped as a consult file. For example, the list
+%% `[a, b, c]' will return the consult file `a. b. c.'.
+create_config(AppDir, Contents) ->
+ Conf = filename:join([AppDir, "rebar.config"]),
+ ok = filelib:ensure_dir(Conf),
+ Config = lists:flatten([io_lib:fwrite("~p.~n", [Term]) || Term <- Contents]),
+ ok = ec_file:write(Conf, Config),
+ Conf.
+
+%% @doc Util to create a random variation of a given name.
+create_random_name(Name) ->
+ random:seed(erlang:now()),
+ Name ++ erlang:integer_to_list(random:uniform(1000000)).
+
+%% @doc Util to create a random variation of a given version.
+create_random_vsn() ->
+ random:seed(erlang:now()),
+ lists:flatten([erlang:integer_to_list(random:uniform(100)),
+ ".", erlang:integer_to_list(random:uniform(100)),
+ ".", erlang:integer_to_list(random:uniform(100))]).
+
+%%%%%%%%%%%%%%%
+%%% Helpers %%%
+%%%%%%%%%%%%%%%
+write_src_file(Dir, Name) ->
+ Erl = filename:join([Dir, "src", "not_a_real_src" ++ Name ++ ".erl"]),
+ ok = filelib:ensure_dir(Erl),
+ ok = ec_file:write(Erl, erl_src_file("not_a_real_src" ++ Name ++ ".erl")).
+
+write_app_file(Dir, Name, Version, Deps) ->
+ Filename = filename:join([Dir, "ebin", Name ++ ".app"]),
+ ok = filelib:ensure_dir(Filename),
+ ok = ec_file:write_term(Filename, get_app_metadata(ec_cnv:to_list(Name), Version, Deps)).
+
+write_app_src_file(Dir, Name, Version, Deps) ->
+ Filename = filename:join([Dir, "src", Name ++ ".app.src"]),
+ ok = filelib:ensure_dir(Filename),
+ ok = ec_file:write_term(Filename, get_app_metadata(ec_cnv:to_list(Name), Version, Deps)).
+
+erl_src_file(Name) ->
+ io_lib:format("-module(~s).\n"
+ "-export([main/0]).\n"
+ "main() -> ok.\n", [filename:basename(Name, ".erl")]).
+
+get_app_metadata(Name, Vsn, Deps) ->
+ {application, erlang:list_to_atom(Name),
+ [{description, ""},
+ {vsn, Vsn},
+ {modules, []},
+ {included_applications, []},
+ {registered, []},
+ {applications, Deps}]}.