diff options
| -rw-r--r-- | src/rebar3.erl | 23 | ||||
| -rw-r--r-- | src/rebar_prv_common_test.erl | 2 | ||||
| -rw-r--r-- | src/rebar_prv_eunit.erl | 70 | ||||
| -rw-r--r-- | src/rebar_utils.erl | 12 | ||||
| -rw-r--r-- | test/rebar_eunit_SUITE.erl | 18 | 
5 files changed, 71 insertions, 54 deletions
| diff --git a/src/rebar3.erl b/src/rebar3.erl index e55db71..2b73844 100644 --- a/src/rebar3.erl +++ b/src/rebar3.erl @@ -96,7 +96,7 @@ run(RawArgs) ->      run_aux(BaseState2, RawArgs).  run_aux(State, RawArgs) -> -    State2 = case os:getenv("REBAR_PROFILE") of +    State1 = case os:getenv("REBAR_PROFILE") of                   false ->                       State;                   "" -> @@ -105,6 +105,9 @@ run_aux(State, RawArgs) ->                       rebar_state:apply_profiles(State, [list_to_atom(Profile)])               end, +    %% bootstrap test profile +    State2 = rebar_state:add_to_profile(State1, test, test_state(State1)), +      %% Process each command, resetting any state between each one      BaseDir = rebar_state:get(State, base_dir, ?DEFAULT_BASE_DIR),      State3 = rebar_state:set(State2, base_dir, @@ -319,3 +322,21 @@ state_from_global_config(Config, GlobalConfigFile) ->      GlobalConfig2 = rebar_state:set(GlobalConfig, plugins, []),      GlobalConfig3 = rebar_state:set(GlobalConfig2, {plugins, global}, rebar_state:get(GlobalConfigThrowAway, plugins, [])),      rebar_state:providers(rebar_state:new(GlobalConfig3, Config), GlobalPlugins). + +test_state(State) -> +    ErlOpts = rebar_state:get(State, erl_opts, []), +    TestOpts = safe_define_test_macro(ErlOpts), +    [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts}]. + +safe_define_test_macro(Opts) -> +    %% defining a compile macro twice results in an exception so +    %% make sure 'TEST' is only defined once +    case test_defined(Opts) of +       true  -> []; +       false -> [{d, 'TEST'}] +    end. + +test_defined([{d, 'TEST'}|_]) -> true; +test_defined([{d, 'TEST', true}|_]) -> true; +test_defined([_|Rest]) -> test_defined(Rest); +test_defined([]) -> false.
\ No newline at end of file diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 1f4c02d..32d4433 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -38,7 +38,7 @@ init(State) ->  -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.  do(State) ->      ?INFO("Running Common Test suites...", []), -    rebar_utils:update_code(rebar_state:code_paths(State, all_deps)), +    rebar_utils:update_code(rebar_state:code_paths(State, all_deps), [soft_purge]),      %% Run ct provider prehooks      Providers = rebar_state:providers(State), diff --git a/src/rebar_prv_eunit.erl b/src/rebar_prv_eunit.erl index b748b06..d5612e8 100644 --- a/src/rebar_prv_eunit.erl +++ b/src/rebar_prv_eunit.erl @@ -9,7 +9,7 @@           do/1,           format_error/1]).  %% exported solely for tests --export([compile/2, prepare_tests/1, eunit_opts/1]). +-export([compile/2, prepare_tests/1, eunit_opts/1, validate_tests/2]).  -include("rebar.hrl").  -include_lib("providers/include/providers.hrl"). @@ -34,8 +34,7 @@ init(State) ->                                   {opts, eunit_opts(State)},                                   {profiles, [test]}]),      State1 = rebar_state:add_provider(State, Provider), -    State2 = rebar_state:add_to_profile(State1, test, test_state(State1)), -    {ok, State2}. +    {ok, State1}.  -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.  do(State) -> @@ -50,14 +49,14 @@ do(State) ->  do(State, Tests) ->      ?INFO("Performing EUnit tests...", []), -    rebar_utils:update_code(rebar_state:code_paths(State, all_deps)), +    rebar_utils:update_code(rebar_state:code_paths(State, all_deps), [soft_purge]),      %% Run eunit provider prehooks      Providers = rebar_state:providers(State),      Cwd = rebar_dir:get_cwd(),      rebar_hooks:run_all_hooks(Cwd, pre, ?PROVIDER, Providers, State), -    case Tests of +    case validate_tests(State, Tests) of          {ok, T} ->              case run_tests(State, T) of                  {ok, State1} -> @@ -103,19 +102,6 @@ format_error({error, Error}) ->  %% Internal functions  %% =================================================================== -test_state(State) -> -    ErlOpts = rebar_state:get(State, erl_opts, []), -    TestOpts = safe_define_test_macro(ErlOpts), -    [{extra_src_dirs, ["test"]}, {erl_opts, TestOpts}]. - -safe_define_test_macro(Opts) -> -    %% defining a compile macro twice results in an exception so -    %% make sure 'TEST' is only defined once -    case test_defined(Opts) of -       true -> Opts; -       false -> [{d, 'TEST'}] ++ Opts -    end. -  compile(State, {ok, Tests}) ->      %% inject `eunit_first_files`, `eunit_compile_opts` and any      %% directories required by tests into the applications @@ -191,11 +177,6 @@ inject_test_dir(Opts, Dir) ->      ExtraSrcDirs = rebar_opts:get(Opts, extra_src_dirs, []),      rebar_opts:set(Opts, extra_src_dirs, ExtraSrcDirs ++ [Dir]). -test_defined([{d, 'TEST'}|_]) -> true; -test_defined([{d, 'TEST', true}|_]) -> true; -test_defined([_|Rest]) -> test_defined(Rest); -test_defined([]) -> false. -  prepare_tests(State) ->      %% parse and translate command line tests      CmdTests = resolve_tests(State), @@ -204,11 +185,7 @@ prepare_tests(State) ->      %% prioritize tests to run first trying any command line specified      %% tests falling back to tests specified in the config file finally      %% running a default set if no other tests are present -    Tests = select_tests(State, ProjectApps, CmdTests, CfgTests), -    %% check applications for existence in project, modules for existence -    %% in applications, files and dirs for existence on disk and allow -    %% any unrecognized tests through for eunit to handle -    validate_tests(State, ProjectApps, Tests). +    select_tests(State, ProjectApps, CmdTests, CfgTests).  resolve_tests(State) ->      {RawOpts, _} = rebar_state:command_parsed_args(State), @@ -231,9 +208,9 @@ resolve(Flag, EUnitKey, RawOpts) ->  normalize(Key, Value) when Key == dir; Key == file -> {Key, Value};  normalize(Key, Value) -> {Key, list_to_atom(Value)}. -select_tests(State, ProjectApps, [], []) -> default_tests(State, ProjectApps); -select_tests(_State, _ProjectApps, [], Tests)  -> Tests; -select_tests(_State, _ProjectApps, Tests, _) -> Tests. +select_tests(State, ProjectApps, [], []) -> {ok, default_tests(State, ProjectApps)}; +select_tests(_State, _ProjectApps, [], Tests)  -> {ok, Tests}; +select_tests(_State, _ProjectApps, Tests, _) -> {ok, Tests}.  default_tests(State, Apps) ->      Tests = set_apps(Apps, []), @@ -252,8 +229,9 @@ set_apps([App|Rest], Acc) ->      AppName = list_to_atom(binary_to_list(rebar_app_info:name(App))),      set_apps(Rest, [{application, AppName}|Acc]). -validate_tests(State, ProjectApps, Tests) -> -    gather_tests(fun(Elem) -> validate(State, ProjectApps, Elem) end, Tests, []). +validate_tests(State, {ok, Tests}) -> +    gather_tests(fun(Elem) -> validate(State, Elem) end, Tests, []); +validate_tests(_State, Error) -> Error.  gather_tests(_F, [], Acc) -> {ok, lists:reverse(Acc)};  gather_tests(F, [Test|Rest], Acc) -> @@ -270,27 +248,31 @@ gather_errors(F, [Test|Rest], Acc) ->          {error, Error} -> gather_errors(F, Rest, [Error|Acc])      end. -validate(State, ProjectApps, {application, App}) -> -    validate_app(State, ProjectApps, App); -validate(State, _ProjectApps, {dir, Dir}) -> +validate(State, {application, App}) -> +    validate_app(State, App); +validate(State, {dir, Dir}) ->      validate_dir(State, Dir); -validate(State, _ProjectApps, {file, File}) -> +validate(State, {file, File}) ->      validate_file(State, File); -validate(State, _ProjectApps, {module, Module}) -> +validate(State, {module, Module}) ->      validate_module(State, Module); -validate(State, _ProjectApps, {suite, Module}) -> +validate(State, {suite, Module}) ->      validate_module(State, Module); -validate(State, _ProjectApps, Module) when is_atom(Module) -> +validate(State, Module) when is_atom(Module) ->      validate_module(State, Module); -validate(State, ProjectApps, Path) when is_list(Path) -> +validate(State, Path) when is_list(Path) ->      case ec_file:is_dir(Path) of -        true  -> validate(State, ProjectApps, {dir, Path}); -        false -> validate(State, ProjectApps, {file, Path}) +        true  -> validate(State, {dir, Path}); +        false -> validate(State, {file, Path})      end;  %% unrecognized tests should be included. if they're invalid eunit will error  %% and rebar.config may contain arbitrarily complex tests that are effectively  %% unvalidatable -validate(_State, _ProjectApps, _Test) -> ok. +validate(_State, _Test) -> ok. + +validate_app(State, AppName) -> +    ProjectApps = rebar_state:project_apps(State), +    validate_app(State, ProjectApps, AppName).  validate_app(_State, [], AppName) ->      {error, lists:concat(["Application `", AppName, "' not found in project."])}; diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 4fd4bd1..ea60e42 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -47,6 +47,7 @@           deprecated/4,           indent/1,           update_code/1, +         update_code/2,           remove_from_code_path/1,           cleanup_code_path/1,           args_to_tasks/1, @@ -644,7 +645,9 @@ indent(Amount) when erlang:is_integer(Amount) ->  %% Replace code paths with new paths for existing apps and  %% purge code of the old modules from those apps. -update_code(Paths) -> +update_code(Paths) -> update_code(Paths, []). + +update_code(Paths, Opts) ->      lists:foreach(fun(Path) ->                            Name = filename:basename(Path, "/ebin"),                            App = list_to_atom(Name), @@ -660,7 +663,12 @@ update_code(Paths) ->                                    %code:replace_path(App, Path),                                    code:del_path(App),                                    code:add_patha(Path), -                                  [begin code:purge(M), code:delete(M) end || M <- Modules] +                                  case lists:member(soft_purge, Opts) of +                                      true  -> +                                          [begin code:soft_purge(M), code:delete(M) end || M <- Modules]; +                                      false -> +                                          [begin code:purge(M), code:delete(M) end || M <- Modules] +                                  end                            end                    end, Paths). diff --git a/test/rebar_eunit_SUITE.erl b/test/rebar_eunit_SUITE.erl index 609be51..262eb92 100644 --- a/test/rebar_eunit_SUITE.erl +++ b/test/rebar_eunit_SUITE.erl @@ -268,7 +268,7 @@ missing_application_arg(Config) ->      State = rebar_state:command_parsed_args(S, Args),      Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Application `missing_app' not found in project."]}}}, -    Error = rebar_prv_eunit:prepare_tests(State). +    Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)).  %% check that the --module cmd line opt generates the correct test set  single_module_arg(Config) -> @@ -311,8 +311,11 @@ missing_module_arg(Config) ->      {ok, Args} = getopt:parse(rebar_prv_eunit:eunit_opts(S), ["--module=missing_app"]),      State = rebar_state:command_parsed_args(S, Args), +    T = rebar_prv_eunit:prepare_tests(State), +    Tests = rebar_prv_eunit:validate_tests(S, T), +      Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}}, -    Error = rebar_prv_eunit:prepare_tests(State). +    Error = Tests.  %% check that the --suite cmd line opt generates the correct test set  single_suite_arg(Config) -> @@ -356,7 +359,7 @@ missing_suite_arg(Config) ->      State = rebar_state:command_parsed_args(S, Args),      Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Module `missing_app' not found in project."]}}}, -    Error = rebar_prv_eunit:prepare_tests(State). +    Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)).  %% check that the --file cmd line opt generates the correct test set  single_file_arg(Config) -> @@ -390,7 +393,7 @@ missing_file_arg(Config) ->      State = rebar_state:command_parsed_args(S, Args),      Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["File `" ++ Path ++"' not found."]}}}, -    Error = rebar_prv_eunit:prepare_tests(State). +    Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)).  %% check that the --dir cmd line opt generates the correct test set  single_dir_arg(Config) -> @@ -424,7 +427,7 @@ missing_dir_arg(Config) ->      State = rebar_state:command_parsed_args(S, Args),      Error = {error, {rebar_prv_eunit, {eunit_test_errors, ["Directory `" ++ Path ++"' not found."]}}}, -    Error = rebar_prv_eunit:prepare_tests(State). +    Error = rebar_prv_eunit:validate_tests(State, rebar_prv_eunit:prepare_tests(State)).  %% check that multiple args are composed  multiple_arg_composition(Config) -> @@ -470,11 +473,14 @@ multiple_arg_errors(Config) ->                                                                "--dir=" ++ DirPath]),      State = rebar_state:command_parsed_args(S, Args), +    T = rebar_prv_eunit:prepare_tests(State), +    Tests = rebar_prv_eunit:validate_tests(S, T), +      Expect = ["Application `missing_app' not found in project.",                "Directory `" ++ DirPath ++ "' not found.",                "File `" ++ FilePath ++ "' not found.",                "Module `missing_app' not found in project.",                "Module `missing_app' not found in project."], -    {error, {rebar_prv_eunit, {eunit_test_errors, Expect}}} = rebar_prv_eunit:prepare_tests(State). +    {error, {rebar_prv_eunit, {eunit_test_errors, Expect}}} = Tests. | 
