Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: juranki/rebar
...
head fork: juranki/rebar
Checking mergeability… Don't worry, you can still create the pull request.
  • 8 commits
  • 7 files changed
  • 0 commit comments
  • 4 contributors
Commits on Feb 21, 2011
@hyperthunk hyperthunk Add -spec support to rebar_ct command line
This change adds support for executing ct test runs based on test
specificiations, which was missing previously. The rebar_ct module
now looks for any number of files with a name ending in `test.spec`
and if it finds one or more, passes these after the `-spec` argument
to ct_run instead of explicitly configuring the config, user config
and coverage config variables.

When no specifications are found, then the module behaves as it did
before this change, and both the ct1 and (new) ct2 integration tests
appear to show this is a backwards compatible patch.
3db8f58
@dysinger dysinger Add fail_on_warning support for LFE 5049da8
@dysinger dysinger Add up to date instructions in case LFE is missing 6f97e6e
@tuncer tuncer Fix Dialyzer warning and slightly reformat code c6f6e8a
@juranki Add a way to run tests to generate config values
Write module 'configure' (configure.erl) and place it in the same
directory with rebar.config.

In rebar config, specify values of form
  {test, Fun, Args}
  Fun = atom()
  Args = list()

When rebar is run, the forms will be replaced with values returned
by erlang:apply(configure, Fun, Args).

Values will be cached in rebar.cache and the cache is refreshed when
rebar.config or configure.erl modification timestamps are newer
than rebar.cache.
a658e7d
@juranki fix naming eca8fba
@juranki fix formatting fb233a8
@juranki fix stupid bug cf04233
View
1  include/rebar.hrl
@@ -15,4 +15,3 @@
-define(ERROR(Str, Args), rebar_log:log(error, Str, Args)).
-define(FMT(Str, Args), lists:flatten(io_lib:format(Str, Args))).
-
View
26 inttest/ct2/ct2_rt.erl
@@ -0,0 +1,26 @@
+-module(ct2_rt).
+
+-compile(export_all).
+
+
+files() ->
+ [{create, "ebin/foo.app", app(foo)},
+ {copy, "../../rebar", "rebar"},
+ {copy, "foo.test.spec", "test/foo.test.spec"},
+ {copy, "foo_SUITE.erl", "test/foo_SUITE.erl"}].
+
+run(_Dir) ->
+ {ok, _} = retest:sh("./rebar compile ct -v"),
+ ok.
+
+%%
+%% Generate the contents of a simple .app file
+%%
+app(Name) ->
+ App = {application, Name,
+ [{description, atom_to_list(Name)},
+ {vsn, "1"},
+ {modules, []},
+ {registered, []},
+ {applications, [kernel, stdlib]}]},
+ io_lib:format("~p.\n", [App]).
View
1  inttest/ct2/foo.test.spec
@@ -0,0 +1 @@
+{suites, "test", all}.
View
10 inttest/ct2/foo_SUITE.erl
@@ -0,0 +1,10 @@
+-module(foo_SUITE).
+
+-include_lib("common_test/include/ct.hrl").
+
+-compile(export_all).
+
+all() -> [foo].
+
+foo(Config) ->
+ io:format("Test: ~p\n", [Config]).
View
100 src/rebar_config.erl
@@ -60,13 +60,19 @@ new(ParentConfig) ->
ConfigFile = filename:join([Dir, ConfName]),
Opts = case file:consult(ConfigFile) of
{ok, Terms} ->
- %% Found a config file with some terms. We need to
+ %% Found a config file with some terms.
+
+ %% Replace terms of form {test, Fun, Args} with values
+ %% generated by functions in configure.erl
+ Terms2 = apply_configuration_tests(Terms),
+
+ %% We need to
%% be able to distinguish between local definitions
%% (i.e. from the file in the cwd) and inherited
%% definitions. To accomplish this, we use a marker
%% in the proplist (since order matters) between
%% the new and old defs.
- Terms ++ [local] ++
+ Terms2 ++ [local] ++
[Opt || Opt <- ParentConfig#config.opts, Opt /= local];
{error, enoent} ->
[local] ++
@@ -124,3 +130,93 @@ local_opts([local | _Rest], Acc) ->
lists:reverse(Acc);
local_opts([Item | Rest], Acc) ->
local_opts(Rest, [Item | Acc]).
+
+apply_configuration_tests(Terms) ->
+ case find_configuration_tests(Terms, []) of
+ [] ->
+ Terms;
+ Tests ->
+ case cache_status() of
+ create ->
+ ok = create_configuration_cache(Tests),
+ ?CONSOLE("Created configuration cache.~n", []);
+ update ->
+ ok = file:delete("rebar.cache"),
+ ok = create_configuration_cache(Tests),
+ ?CONSOLE("Updated configuration cache.~n", []);
+ ok ->
+ ok
+ end,
+ replace_configuration_values(Terms)
+ end.
+
+find_configuration_tests([], Acc) ->
+ Acc;
+find_configuration_tests([{test, Fun, Args} | Rest], Acc) ->
+ Acc2 = case lists:member({Fun, Args}, Acc) of
+ true ->
+ Acc;
+ false ->
+ [{Fun, Args} | Acc]
+ end,
+ find_configuration_tests(Rest, Acc2);
+find_configuration_tests([Term | Rest], Acc) when is_list(Term) ->
+ find_configuration_tests(Term ++ Rest, Acc);
+find_configuration_tests([Term | Rest], Acc) when is_tuple(Term) ->
+ find_configuration_tests(tuple_to_list(Term) ++ Rest, Acc);
+find_configuration_tests([_Term | Rest], Acc) ->
+ find_configuration_tests(Rest, Acc).
+
+cache_status() ->
+ Cache = filelib:last_modified("rebar.cache"), %% 0 if not found
+ RebarConfig = filelib:last_modified("rebar.config"),
+ ConfigureErl = filelib:last_modified("configure.erl"),
+ if
+ Cache == 0 -> create;
+ Cache < RebarConfig -> update;
+ Cache < ConfigureErl -> update;
+ true -> ok
+ end.
+
+create_configuration_cache(Tests) ->
+ case compile:file("configure", [binary, debug_info, report]) of
+ {ok, _, Bin} ->
+ {module, _} = code:load_binary(configure, "configure", Bin),
+ Vals = [io_lib:format("~w.~n",
+ [{{Test, Args},
+ erlang:apply(configure, Test, Args)}])
+ || {Test, Args} <- Tests],
+ ok = file:write_file("rebar.cache", Vals),
+ true = code:delete(configure),
+ ok;
+ _ ->
+ ?ABORT("Failed to compile configuration tests.", [])
+ end.
+
+replace_configuration_values(ConfigTerms) ->
+ case file:consult("rebar.cache") of
+ {ok, CacheTerms} ->
+ replace_configuration_values(ConfigTerms, CacheTerms, []);
+ _ ->
+ ?ABORT("Failed to read rebar.cache.", [])
+ end.
+
+replace_configuration_values([], _, Acc) ->
+ lists:reverse(Acc);
+replace_configuration_values([{test, Fun, Args} | Rest], ConfigTerms, Acc) ->
+ replace_configuration_values(Rest, ConfigTerms,
+ [proplists:get_value({Fun, Args}, ConfigTerms)
+ | Acc]);
+replace_configuration_values([Term | Rest], ConfigTerms, Acc)
+ when is_list(Term) ->
+ List = replace_configuration_values(Term, ConfigTerms, []),
+ replace_configuration_values(Rest, ConfigTerms,
+ [List | Acc]);
+replace_configuration_values([Term | Rest], ConfigTerms, Acc)
+ when is_tuple(Term) ->
+ Tuple = list_to_tuple(
+ replace_configuration_values(tuple_to_list(Term),
+ ConfigTerms, [])),
+ replace_configuration_values(Rest, ConfigTerms, [Tuple | Acc]);
+replace_configuration_values([Term | Rest], ConfigTerms, Acc) ->
+ replace_configuration_values(Rest, ConfigTerms, [Term | Acc]).
View
70 src/rebar_ct.erl
@@ -141,32 +141,57 @@ make_cmd(TestDir, Config) ->
CodeDirs = [io_lib:format("\"~s\"", [Dir]) ||
Dir <- [EbinDir|NonLibCodeDirs]],
CodePathString = string:join(CodeDirs, " "),
- Cmd = ?FMT("erl " % should we expand ERL_PATH?
- " -noshell -pa ~s ~s"
- " -s ct_run script_start -s erlang halt"
- " -name test@~s"
- " -logdir \"~s\""
- " -env TEST_DIR \"~s\"",
- [CodePathString,
- Include,
- net_adm:localhost(),
- LogDir,
- filename:join(Cwd, TestDir)]) ++
- get_cover_config(Config, Cwd) ++
- get_ct_config_file(TestDir) ++
- get_config_file(TestDir) ++
- get_suite(TestDir) ++
- get_case(),
+ Cmd = case get_ct_specs(Cwd) of
+ undefined ->
+ ?FMT("erl " % should we expand ERL_PATH?
+ " -noshell -pa ~s ~s"
+ " -s ct_run script_start -s erlang halt"
+ " -name test@~s"
+ " -logdir \"~s\""
+ " -env TEST_DIR \"~s\"",
+ [CodePathString,
+ Include,
+ net_adm:localhost(),
+ LogDir,
+ filename:join(Cwd, TestDir)]) ++
+ get_cover_config(Config, Cwd) ++
+ get_ct_config_file(TestDir) ++
+ get_config_file(TestDir) ++
+ get_suite(TestDir) ++
+ get_case();
+ SpecFlags ->
+ ?FMT("erl " % should we expand ERL_PATH?
+ " -noshell -pa ~s ~s"
+ " -s ct_run script_start -s erlang halt"
+ " -name test@~s"
+ " -logdir \"~s\""
+ " -env TEST_DIR \"~s\"",
+ [CodePathString,
+ Include,
+ net_adm:localhost(),
+ LogDir,
+ filename:join(Cwd, TestDir)]) ++
+ SpecFlags ++ get_cover_config(Config, Cwd)
+ end,
RawLog = filename:join(LogDir, "raw.log"),
{Cmd, RawLog}.
+get_ct_specs(Cwd) ->
+ case collect_glob(Cwd, ".*\.test\.spec\$") of
+ [] -> undefined;
+ [Spec] ->
+ " -spec " ++ Spec;
+ Specs ->
+ " -spec " ++
+ lists:flatten([io_lib:format("~s ", [Spec]) || Spec <- Specs])
+ end.
+
get_cover_config(Config, Cwd) ->
case rebar_config:get_local(Config, cover_enabled, false) of
false ->
"";
true ->
- case filelib:fold_files(Cwd, ".*cover\.spec\$",
- true, fun collect_ct_specs/2, []) of
+ case collect_glob(Cwd, ".*cover\.spec\$") of
[] ->
?DEBUG("No cover spec found: ~s~n", [Cwd]),
"";
@@ -178,15 +203,18 @@ get_cover_config(Config, Cwd) ->
end
end.
-collect_ct_specs(F, Acc) ->
+collect_glob(Cwd, Glob) ->
+ filelib:fold_files(Cwd, Glob, true, fun collect_files/2, []).
+
+collect_files(F, Acc) ->
%% Ignore any specs under the deps/ directory. Do this pulling
%% the dirname off the the F and then splitting it into a list.
Parts = filename:split(filename:dirname(F)),
case lists:member("deps", Parts) of
true ->
- Acc; % There is a directory named "deps" in path
+ Acc; % There is a directory named "deps" in path
false ->
- [F | Acc] % No "deps" directory in path
+ [F | Acc] % No "deps" directory in path
end.
get_ct_config_file(TestDir) ->
View
36 src/rebar_lfe_compiler.erl
@@ -41,27 +41,39 @@ compile(Config, _AppFile) ->
rebar_base_compiler:run(Config, FirstFiles, "src", ".lfe", "ebin", ".beam",
fun compile_lfe/3).
-
%% ===================================================================
%% Internal functions
%% ===================================================================
-compile_lfe(Source, _Target, Config) ->
+compile_lfe(Source, Target, Config) ->
case code:which(lfe_comp) of
non_existing ->
- ?CONSOLE(
- <<"~n===============================================~n"
- " You need to install LFE to compile LFE source files~n"
- "Download the latest tarball release from github~n"
- " https://github.com/rvirding/lfe/downloads~n"
- " and install it into your erlang library dir~n"
- "===============================================~n~n">>, []),
+ ?CONSOLE(<<
+ "~n"
+ "*** MISSING LFE COMPILER ***~n"
+ " You must do one of the following:~n"
+ " a) Install LFE globally in your erl libs~n"
+ " b) Add LFE as a dep for your project, eg:~n"
+ " {lfe, \"0.6.1\",~n"
+ " {git, \"git://github.com/rvirding/lfe\",~n"
+ " {tag, \"v0.6.1\"}}}~n"
+ "~n"
+ >>, []),
?FAIL;
_ ->
Opts = [{i, "include"}, {outdir, "ebin"}, report, return] ++
- rebar_config:get_list(Config, lfe_opts, []),
- case lfe_comp:file(Source,Opts) of
- {ok, _, []} -> ok;
+ rebar_config:get_list(Config, erl_opts, []),
+ case lfe_comp:file(Source, Opts) of
+ {ok, _, []} ->
+ ok;
+ {ok, _, _Warnings} ->
+ case lists:member(fail_on_warning, Opts) of
+ true ->
+ ok = file:delete(Target),
+ ?FAIL;
+ false ->
+ ok
+ end;
_ -> ?FAIL
end
end.

No commit comments for this range

Something went wrong with that request. Please try again.