From 48c372d68dbe87b7a6d929e815b3250d63de820d Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Sun, 20 Dec 2015 15:19:32 -0800 Subject: [PATCH 1/4] whitespace cleanup --- src/rebar_prv_common_test.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 05a1dc6a..bc1707ef 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -340,7 +340,7 @@ test_dirs(State, Apps, Opts) -> {Suites, Dir} when is_integer(hd(Dir)) -> set_compile_dirs(State, Apps, join(Suites, Dir)); {Suites, [Dir]} when is_integer(hd(Dir)) -> - set_compile_dirs(State, Apps, join(Suites, Dir)); + set_compile_dirs(State, Apps, join(Suites, Dir)); {_Suites, _Dirs} -> {error, "Only a single directory may be specified when specifying suites"} end. From 9acd23f72799c6130b9f7a2c226346dcd10ac2c8 Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Sun, 20 Dec 2015 16:17:05 -0800 Subject: [PATCH 2/4] allow ct suites to be specified at the root of a project (or root of app) previously rebar3 dropped suites declared at the root of the project (via `--suite=whatever_SUITE' probably) and warned. this was because the compiler would recursively copy and compile everything in the directory indicated by the test suite. this changes the copy mechanism to only copy erl source files and directories that end with `_SUITE_data' into the `extras' dir in `_build' --- src/rebar_prv_common_test.erl | 29 ++++++++++++++++++++-- src/rebar_prv_compile.erl | 4 +++ test/rebar_ct_SUITE.erl | 46 ++++++++++++++++++++++++++++++++++- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index bc1707ef..2a76ebba 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -375,6 +375,16 @@ find_suite_dirs(Suites) -> maybe_inject_test_dir(State, AppAcc, [App|Rest], Dir) -> case rebar_file_utils:path_from_ancestor(Dir, rebar_app_info:dir(App)) of + {ok, []} -> + %% normal operation involves copying the entire directory a + %% suite exists in but if the suite is in the app root directory + %% the current compiler tries to compile all subdirs including priv + %% instead copy only files ending in `.erl' and directories + %% ending in `_SUITE_data' into the `_build/PROFILE/extras' dir + ExtrasDir = filename:join([rebar_dir:base_dir(State), "extras"]), + ok = copy_bare_suites(Dir, ExtrasDir), + Opts = inject_test_dir(rebar_state:opts(State), ExtrasDir), + {rebar_state:opts(State, Opts), AppAcc}; {ok, Path} -> Opts = inject_test_dir(rebar_app_info:opts(App), Path), {State, AppAcc ++ [rebar_app_info:opts(App, Opts)] ++ Rest}; @@ -384,8 +394,15 @@ maybe_inject_test_dir(State, AppAcc, [App|Rest], Dir) -> maybe_inject_test_dir(State, AppAcc, [], Dir) -> case rebar_file_utils:path_from_ancestor(Dir, rebar_state:dir(State)) of {ok, []} -> - ?WARN("Can't have suites in root of project dir, dropping from tests", []), - {State, AppAcc}; + %% normal operation involves copying the entire directory a + %% suite exists in but if the suite is in the root directory + %% that results in a loop as we copy `_build' into itself + %% instead copy only files ending in `.erl' and directories + %% ending in `_SUITE_data' in the `_build/PROFILE/extras' dir + ExtrasDir = filename:join([rebar_dir:base_dir(State), "extras"]), + ok = copy_bare_suites(Dir, ExtrasDir), + Opts = inject_test_dir(rebar_state:opts(State), ExtrasDir), + {rebar_state:opts(State, Opts), AppAcc}; {ok, Path} -> Opts = inject_test_dir(rebar_state:opts(State), Path), {rebar_state:opts(State, Opts), AppAcc}; @@ -393,6 +410,14 @@ maybe_inject_test_dir(State, AppAcc, [], Dir) -> {State, AppAcc} end. +copy_bare_suites(From, To) -> + filelib:ensure_dir(filename:join([To, "dummy.txt"])), + SrcFiles = rebar_utils:find_files(From, ".*\\.[e|h]rl\$", false), + DataDirs = lists:filter(fun filelib:is_dir/1, + filelib:wildcard(filename:join([From, "*_SUITE_data"]))), + ok = rebar_file_utils:cp_r(SrcFiles, To), + rebar_file_utils:cp_r(DataDirs, To). + inject_test_dir(Opts, Dir) -> %% append specified test targets to app defined `extra_src_dirs` ExtraSrcDirs = rebar_opts:get(Opts, extra_src_dirs, []), diff --git a/src/rebar_prv_compile.erl b/src/rebar_prv_compile.erl index 2996aeeb..d57b82b2 100644 --- a/src/rebar_prv_compile.erl +++ b/src/rebar_prv_compile.erl @@ -217,6 +217,10 @@ copy(OldAppDir, AppDir, Dir) -> %% TODO: use ec_file:copy/2 to do this, it preserves timestamps and %% may prevent recompilation of files in extra dirs +copy(Source, Source) -> + %% allow users to specify a directory in _build as a directory + %% containing additional source/tests + ok; copy(Source, Target) -> %% important to do this so no files are copied onto themselves %% which truncates them to zero length on some platforms diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl index 267a9eee..41a7c801 100644 --- a/test/rebar_ct_SUITE.erl +++ b/test/rebar_ct_SUITE.erl @@ -17,6 +17,7 @@ multi_suite/1, all_suite/1, single_dir_and_single_suite/1, + suite_at_root/1, data_dir_correct/1, cmd_label/1, cmd_config/1, @@ -72,7 +73,8 @@ groups() -> [{basic_app, [], [basic_app_default_dirs, single_unmanaged_suite, multi_suite, all_suite, - single_dir_and_single_suite]}, + single_dir_and_single_suite, + suite_at_root]}, {data_dirs, [], [data_dir_correct]}, {ct_opts, [], [cmd_label, cmd_config, @@ -177,6 +179,14 @@ init_per_group(dirs_and_suites, Config) -> ok = filelib:ensure_dir(Suite3), ok = file:write_file(Suite3, test_suite("extras")), + Suite4 = filename:join([AppDir, "root_SUITE.erl"]), + ok = file:write_file(Suite4, test_suite("root")), + + ok = file:write_file(filename:join([AppDir, "root_SUITE.hrl"]), <<>>), + + ok = filelib:ensure_dir(filename:join([AppDir, "root_SUITE_data", "dummy.txt"])), + ok = file:write_file(filename:join([AppDir, "root_SUITE_data", "some_data.txt"]), <<>>), + {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), [{s, State}, {appnames, [Name1, Name2]}|C]; @@ -603,6 +613,40 @@ single_dir_and_single_suite(Config) -> Suite = proplists:get_value(suite, Opts), ["extra_SUITE"] = Suite. +suite_at_root(Config) -> + AppDir = ?config(apps, Config), + State = ?config(s, Config), + + LibDirs = rebar_dir:lib_dirs(State), + State1 = rebar_app_discover:do(State, LibDirs), + + Providers = rebar_state:providers(State1), + Namespace = rebar_state:namespace(State1), + CommandProvider = providers:get_provider(ct, Providers, Namespace), + GetOptSpec = providers:opts(CommandProvider), + {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join([AppDir, "root_SUITE"])]), + + State2 = rebar_state:command_parsed_args(State1, GetOptResult), + + Tests = rebar_prv_common_test:prepare_tests(State2), + {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), + {ok, T} = Tests, + Opts = rebar_prv_common_test:translate_paths(NewState, T), + + Suite = proplists:get_value(suite, Opts), + Expected = filename:join([AppDir, "_build", "test", "extras", "root_SUITE"]), + [Expected] = Suite, + + TestHrl = filename:join([AppDir, "_build", "test", "extras", "root_SUITE.hrl"]), + true = filelib:is_file(TestHrl), + + TestBeam = filename:join([AppDir, "_build", "test", "extras", "root_SUITE.beam"]), + true = filelib:is_file(TestBeam), + + DataDir = filename:join([AppDir, "_build", "test", "extras", "root_SUITE_data"]), + true = filelib:is_dir(DataDir). + + %% this test probably only fails when this suite is run via rebar3 with the --cover flag data_dir_correct(Config) -> DataDir = ?config(data_dir, Config), From 639906bdb531160d7d6a0322acfd7672b48a5387 Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Sun, 20 Dec 2015 18:47:05 -0800 Subject: [PATCH 3/4] put `extra' ct test suites in `extras/apps/APPNAME' rather than `extras' this allows repeated test suite names across apps without conflicts --- src/rebar_prv_common_test.erl | 3 ++- test/rebar_ct_SUITE.erl | 45 ++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 2a76ebba..1136e08e 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -381,7 +381,8 @@ maybe_inject_test_dir(State, AppAcc, [App|Rest], Dir) -> %% the current compiler tries to compile all subdirs including priv %% instead copy only files ending in `.erl' and directories %% ending in `_SUITE_data' into the `_build/PROFILE/extras' dir - ExtrasDir = filename:join([rebar_dir:base_dir(State), "extras"]), + {ok, RelAppDir} = rebar_file_utils:path_from_ancestor(rebar_app_info:dir(App), rebar_state:dir(State)), + ExtrasDir = filename:join([rebar_dir:base_dir(State), "extras", RelAppDir]), ok = copy_bare_suites(Dir, ExtrasDir), Opts = inject_test_dir(rebar_state:opts(State), ExtrasDir), {rebar_state:opts(State, Opts), AppAcc}; diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl index 41a7c801..d572cc27 100644 --- a/test/rebar_ct_SUITE.erl +++ b/test/rebar_ct_SUITE.erl @@ -18,6 +18,7 @@ all_suite/1, single_dir_and_single_suite/1, suite_at_root/1, + suite_at_app_root/1, data_dir_correct/1, cmd_label/1, cmd_config/1, @@ -74,7 +75,8 @@ groups() -> [{basic_app, [], [basic_app_default_dirs, multi_suite, all_suite, single_dir_and_single_suite, - suite_at_root]}, + suite_at_root, + suite_at_app_root]}, {data_dirs, [], [data_dir_correct]}, {ct_opts, [], [cmd_label, cmd_config, @@ -187,6 +189,14 @@ init_per_group(dirs_and_suites, Config) -> ok = filelib:ensure_dir(filename:join([AppDir, "root_SUITE_data", "dummy.txt"])), ok = file:write_file(filename:join([AppDir, "root_SUITE_data", "some_data.txt"]), <<>>), + Suite5 = filename:join([AppDir, "apps", Name2, "app_root_SUITE.erl"]), + ok = file:write_file(Suite5, test_suite("app_root")), + + ok = file:write_file(filename:join([AppDir, "apps", Name2, "app_root_SUITE.hrl"]), <<>>), + + ok = filelib:ensure_dir(filename:join([AppDir, "apps", Name2, "app_root_SUITE_data", "dummy.txt"])), + ok = file:write_file(filename:join([AppDir, "apps", Name2, "app_root_SUITE_data", "some_data.txt"]), <<>>), + {ok, State} = rebar_test_utils:run_and_check(C, [], ["as", "test", "lock"], return), [{s, State}, {appnames, [Name1, Name2]}|C]; @@ -646,6 +656,39 @@ suite_at_root(Config) -> DataDir = filename:join([AppDir, "_build", "test", "extras", "root_SUITE_data"]), true = filelib:is_dir(DataDir). +suite_at_app_root(Config) -> + AppDir = ?config(apps, Config), + [_Name1, Name2] = ?config(appnames, Config), + State = ?config(s, Config), + + LibDirs = rebar_dir:lib_dirs(State), + State1 = rebar_app_discover:do(State, LibDirs), + + Providers = rebar_state:providers(State1), + Namespace = rebar_state:namespace(State1), + CommandProvider = providers:get_provider(ct, Providers, Namespace), + GetOptSpec = providers:opts(CommandProvider), + {ok, GetOptResult} = getopt:parse(GetOptSpec, ["--suite=" ++ filename:join([AppDir, "apps", Name2, "app_root_SUITE"])]), + + State2 = rebar_state:command_parsed_args(State1, GetOptResult), + + Tests = rebar_prv_common_test:prepare_tests(State2), + {ok, NewState} = rebar_prv_common_test:compile(State2, Tests), + {ok, T} = Tests, + Opts = rebar_prv_common_test:translate_paths(NewState, T), + + Suite = proplists:get_value(suite, Opts), + Expected = filename:join([AppDir, "_build", "test", "extras", "apps", Name2, "app_root_SUITE"]), + [Expected] = Suite, + + TestHrl = filename:join([AppDir, "_build", "test", "extras", "apps", Name2, "app_root_SUITE.hrl"]), + true = filelib:is_file(TestHrl), + + TestBeam = filename:join([AppDir, "_build", "test", "extras", "apps", Name2, "app_root_SUITE.beam"]), + true = filelib:is_file(TestBeam), + + DataDir = filename:join([AppDir, "_build", "test", "extras", "apps", Name2, "app_root_SUITE_data"]), + true = filelib:is_dir(DataDir). %% this test probably only fails when this suite is run via rebar3 with the --cover flag data_dir_correct(Config) -> From a4711d00ac294328494de620b2e66067ff80785c Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Sun, 20 Dec 2015 19:26:00 -0800 Subject: [PATCH 4/4] add test for foo_SUITE_data files --- test/rebar_ct_SUITE.erl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/rebar_ct_SUITE.erl b/test/rebar_ct_SUITE.erl index d572cc27..183a1d07 100644 --- a/test/rebar_ct_SUITE.erl +++ b/test/rebar_ct_SUITE.erl @@ -654,7 +654,10 @@ suite_at_root(Config) -> true = filelib:is_file(TestBeam), DataDir = filename:join([AppDir, "_build", "test", "extras", "root_SUITE_data"]), - true = filelib:is_dir(DataDir). + true = filelib:is_dir(DataDir), + + DataFile = filename:join([AppDir, "_build", "test", "extras", "root_SUITE_data", "some_data.txt"]), + true = filelib:is_file(DataFile). suite_at_app_root(Config) -> AppDir = ?config(apps, Config), @@ -688,7 +691,10 @@ suite_at_app_root(Config) -> true = filelib:is_file(TestBeam), DataDir = filename:join([AppDir, "_build", "test", "extras", "apps", Name2, "app_root_SUITE_data"]), - true = filelib:is_dir(DataDir). + true = filelib:is_dir(DataDir), + + DataFile = filename:join([AppDir, "_build", "test", "extras", "root_SUITE_data", "some_data.txt"]), + true = filelib:is_file(DataFile). %% this test probably only fails when this suite is run via rebar3 with the --cover flag data_dir_correct(Config) ->