From a5bdf11770a8b57f7db2ca28f14dbf66c43673db Mon Sep 17 00:00:00 2001 From: Alexander Sedov Date: Thu, 4 Aug 2016 15:06:47 +0300 Subject: Typo fix. --- src/rebar_prv_common_test.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index fbd0e89..1e0632e 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -221,7 +221,7 @@ select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> Configs = lists:flatmap(fun(Filename) -> rebar_file_utils:consult_config(State, Filename) end, SysConfigs), - [application:load(Application) || Config <- SysConfigs, {Application, _} <- Config], + [application:load(Application) || Config <- Configs, {Application, _} <- Config], rebar_utils:reread_config(Configs), Merged = lists:ukeymerge(1, -- cgit v1.1 From 3966610e532f18f71c6e4d04c3a96d6372ddc390 Mon Sep 17 00:00:00 2001 From: Alexander Sedov Date: Tue, 11 Oct 2016 10:31:57 +0300 Subject: Made Common Test load the user's applications before slurping config. --- src/rebar_prv_common_test.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 1e0632e..8bfa192 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -221,6 +221,7 @@ select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> Configs = lists:flatmap(fun(Filename) -> rebar_file_utils:consult_config(State, Filename) end, SysConfigs), + code:add_pathsa(rebar_state:code_paths(State, all_deps)), [application:load(Application) || Config <- Configs, {Application, _} <- Config], rebar_utils:reread_config(Configs), -- cgit v1.1 From 0afb4c4d477b1c1fba54ad3ef086d0697a5faeaa Mon Sep 17 00:00:00 2001 From: Alexander Sedov Date: Tue, 11 Oct 2016 10:36:12 +0300 Subject: Made reading sys.configs consistent with OTP specification. --- src/rebar_prv_common_test.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 8bfa192..e69d33e 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -218,9 +218,9 @@ select_tests(_, _, _, {error, _} = Error) -> Error; select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> %% set application env if sys_config argument is provided SysConfigs = sys_config_list(CmdOpts, CfgOpts), - Configs = lists:flatmap(fun(Filename) -> - rebar_file_utils:consult_config(State, Filename) - end, SysConfigs), + Configs = lists:map(fun(Filename) -> + rebar_file_utils:consult_config(State, Filename) + end, SysConfigs), code:add_pathsa(rebar_state:code_paths(State, all_deps)), [application:load(Application) || Config <- Configs, {Application, _} <- Config], rebar_utils:reread_config(Configs), -- cgit v1.1 From 4ce21e4c800108030d5c646b226032f460e68065 Mon Sep 17 00:00:00 2001 From: Alexander Sedov Date: Tue, 11 Oct 2016 16:30:27 +0300 Subject: Avoid backward-compatibility-breaking changes. --- src/rebar_prv_common_test.erl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index e69d33e..8bfa192 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -218,9 +218,9 @@ select_tests(_, _, _, {error, _} = Error) -> Error; select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> %% set application env if sys_config argument is provided SysConfigs = sys_config_list(CmdOpts, CfgOpts), - Configs = lists:map(fun(Filename) -> - rebar_file_utils:consult_config(State, Filename) - end, SysConfigs), + Configs = lists:flatmap(fun(Filename) -> + rebar_file_utils:consult_config(State, Filename) + end, SysConfigs), code:add_pathsa(rebar_state:code_paths(State, all_deps)), [application:load(Application) || Config <- Configs, {Application, _} <- Config], rebar_utils:reread_config(Configs), -- cgit v1.1 From e71b80752f905d9f4bb5dbf78c16693dbc6133f4 Mon Sep 17 00:00:00 2001 From: Alexander Sedov Date: Tue, 11 Oct 2016 16:34:21 +0300 Subject: Some post-review changes: - restore path after loading applications, - helpful comments. --- src/rebar_prv_common_test.erl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 8bfa192..46bd1a7 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -221,9 +221,13 @@ select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> Configs = lists:flatmap(fun(Filename) -> rebar_file_utils:consult_config(State, Filename) end, SysConfigs), + %% NB: load the applications (from user directories too) to support OTP < 17 + %% to our best ability. + OldPath = code:get_path(), code:add_pathsa(rebar_state:code_paths(State, all_deps)), [application:load(Application) || Config <- Configs, {Application, _} <- Config], rebar_utils:reread_config(Configs), + code:set_path(OldPath), Merged = lists:ukeymerge(1, lists:ukeysort(1, CmdOpts), -- cgit v1.1 From 203e5c15bd1935d66ca29fb071a8bc7ba8dad162 Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Mon, 17 Oct 2016 17:10:41 -0700 Subject: allow test specifications to be passed via the command line `rebar3 ct --spec foo.spec,bar.spec,baz.spec` now works also added support for the `join_specs` flag on the command line --- src/rebar_prv_common_test.erl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 46bd1a7..189a26f 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -139,6 +139,8 @@ transform_opts([{testcase, Cases}|Rest], Acc) -> transform_opts(Rest, [{testcase, split_string(Cases)}|Acc]); transform_opts([{config, Configs}|Rest], Acc) -> transform_opts(Rest, [{config, split_string(Configs)}|Acc]); +transform_opts([{spec, Specs}|Rest], Acc) -> + transform_opts(Rest, [{spec, split_string(Specs)}|Acc]); transform_opts([{include, Includes}|Rest], Acc) -> transform_opts(Rest, [{include, split_string(Includes)}|Acc]); transform_opts([{logopts, LogOpts}|Rest], Acc) -> @@ -174,9 +176,6 @@ cfgopts(State) -> end. ensure_opts([], Acc) -> lists:reverse(Acc); -ensure_opts([{test_spec, _}|Rest], Acc) -> - ?WARN("Test specs not supported. See http://www.rebar3.org/docs/running-tests#common-test", []), - ensure_opts(Rest, Acc); ensure_opts([{cover, _}|Rest], Acc) -> ?WARN("Cover specs not supported. See http://www.rebar3.org/docs/running-tests#common-test", []), ensure_opts(Rest, Acc); @@ -650,6 +649,8 @@ ct_opts(_State) -> {testcase, undefined, "case", string, help(testcase)}, %% comma-seperated list {label, undefined, "label", string, help(label)}, %% String {config, undefined, "config", string, help(config)}, %% comma-seperated list + {spec, undefined, "spec", string, help(spec)}, %% common-seperated list + {join_specs, undefined, "join_specs", boolean, help(join_specs)}, {allow_user_terms, undefined, "allow_user_terms", boolean, help(allow_user_terms)}, %% Bool {logdir, undefined, "logdir", string, help(logdir)}, %% dir {logopts, undefined, "logopts", string, help(logopts)}, %% comma seperated list @@ -688,6 +689,10 @@ help(label) -> "Test label"; help(config) -> "List of config files"; +help(spec) -> + "List of test specifications"; +help(join_specs) -> + "Merge all test specifications and perform a single test run"; help(sys_config) -> "List of application config files"; help(allow_user_terms) -> -- cgit v1.1 From 14956eaf168dd20b0b1da1c05a82d66da77ec37c Mon Sep 17 00:00:00 2001 From: alisdair sullivan Date: Mon, 17 Oct 2016 18:52:09 -0700 Subject: fix "helpful" compiler spelling correction --- src/rebar_prv_common_test.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 189a26f..b91c90f 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -649,7 +649,7 @@ ct_opts(_State) -> {testcase, undefined, "case", string, help(testcase)}, %% comma-seperated list {label, undefined, "label", string, help(label)}, %% String {config, undefined, "config", string, help(config)}, %% comma-seperated list - {spec, undefined, "spec", string, help(spec)}, %% common-seperated list + {spec, undefined, "spec", string, help(spec)}, %% comma-seperated list {join_specs, undefined, "join_specs", boolean, help(join_specs)}, {allow_user_terms, undefined, "allow_user_terms", boolean, help(allow_user_terms)}, %% Bool {logdir, undefined, "logdir", string, help(logdir)}, %% dir -- cgit v1.1 From e85cf555e24b2a4b9b8681b9028c87826a2c0ea6 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sat, 19 Nov 2016 16:15:43 -0500 Subject: Fix rebar3 dialyzer warnings Some tricky changes in there but should be okay --- src/rebar_prv_common_test.erl | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index b91c90f..be31e8c 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -212,7 +212,6 @@ add_hooks(Opts, State) -> lists:keyreplace(ct_hooks, 1, Opts, {ct_hooks, NewHooks}) end. -select_tests(_, _, {error, _} = Error, _) -> Error; select_tests(_, _, _, {error, _} = Error) -> Error; select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> %% set application env if sys_config argument is provided @@ -293,14 +292,9 @@ compile(State, {ok, _} = Tests) -> compile(_State, Error) -> Error. do_compile(State) -> - case rebar_prv_compile:do(State) of - %% successfully compiled apps - {ok, S} -> - ok = maybe_cover_compile(S), - {ok, S}; - %% this should look like a compiler error, not an eunit error - Error -> Error - end. + {ok, S} = rebar_prv_compile:do(State), + ok = maybe_cover_compile(S), + {ok, S}. inject_ct_state(State, {ok, Tests}) -> Apps = rebar_state:project_apps(State), @@ -308,8 +302,7 @@ inject_ct_state(State, {ok, Tests}) -> {ok, {NewState, ModdedApps}} -> test_dirs(NewState, ModdedApps, Tests); {error, _} = Error -> Error - end; -inject_ct_state(_State, Error) -> Error. + end. inject_ct_state(State, Tests, [App|Rest], Acc) -> case inject(rebar_app_info:opts(App), State, Tests) of -- cgit v1.1 From 85e00f2a434d3295d7a683838cda002403f5af17 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 28 Nov 2016 11:45:21 +0100 Subject: Improve merge of command line options and config options Bug: option 'spec' is not specifically handled when merging options from the command line with options from rebar.config. Due to this, if the config specifies a 'spec', then this will take precedence over any 'dir' and/or 'suite' on the command line. This commit takes special care of all options that can be used to select tests - meaning that if any of the options 'spec', 'dir', 'suite', 'group' or 'case' are specified on the command line, then all 'spec', 'dir', 'suite', 'group' and 'case' options in rebar.config will be ignored. --- src/rebar_prv_common_test.erl | 77 +++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 25 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index be31e8c..5fa7ae4 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -227,20 +227,42 @@ select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> rebar_utils:reread_config(Configs), code:set_path(OldPath), - Merged = lists:ukeymerge(1, - lists:ukeysort(1, CmdOpts), - lists:ukeysort(1, CfgOpts)), - %% make sure `dir` and/or `suite` from command line go in as - %% a pair overriding both `dir` and `suite` from config if - %% they exist - Opts = case {proplists:get_value(suite, CmdOpts), proplists:get_value(dir, CmdOpts)} of - {undefined, undefined} -> Merged; - {_Suite, undefined} -> lists:keydelete(dir, 1, Merged); - {undefined, _Dir} -> lists:keydelete(suite, 1, Merged); - {_Suite, _Dir} -> Merged - end, + Opts = merge_opts(CmdOpts,CfgOpts), discover_tests(State, ProjectApps, Opts). +%% Merge the option lists from command line and rebar.config: +%% +%% - Options set on the command line will replace the same options if +%% set in rebar.config. +%% +%% - Special care is taken with options that select which tests to +%% run - ANY such option on the command line will replace ALL such +%% options in the config. +%% +%% Note that if 'spec' is given, common_test will ignore all 'dir', +%% 'suite', 'group' and 'case', so there is no need to explicitly +%% remove any options from the command line. +%% +%% All faulty combinations of options are also handled by +%% common_test and are not taken into account here. +merge_opts(CmdOpts0, CfgOpts0) -> + TestSelectOpts = [spec,dir,suite,group,testcase], + CmdOpts = lists:ukeysort(1, CmdOpts0), + CfgOpts1 = lists:ukeysort(1, CfgOpts0), + CfgOpts = case is_any_defined(TestSelectOpts,CmdOpts) of + false -> + CfgOpts1; + true -> + [Opt || Opt={K,_} <- CfgOpts1, + not lists:member(K,TestSelectOpts)] + end, + lists:ukeymerge(1, CmdOpts, CfgOpts). + +is_any_defined([Key|Keys],Opts) -> + proplists:is_defined(Key,Opts) orelse is_any_defined(Keys,Opts); +is_any_defined([],_Opts) -> + false. + sys_config_list(CmdOpts, CfgOpts) -> CmdSysConfigs = split_string(proplists:get_value(sys_config, CmdOpts, "")), case proplists:get_value(sys_config, CfgOpts, []) of @@ -253,11 +275,10 @@ sys_config_list(CmdOpts, CfgOpts) -> end. discover_tests(State, ProjectApps, Opts) -> - case {proplists:get_value(suite, Opts), proplists:get_value(dir, Opts)} of - %% no dirs or suites defined, try using `$APP/test` and `$ROOT/test` - %% as suites - {undefined, undefined} -> {ok, [default_tests(State, ProjectApps)|Opts]}; - {_, _} -> {ok, Opts} + case is_any_defined([spec,dir,suite],Opts) of + %% no tests defined, try using `$APP/test` and `$ROOT/test` as dirs + false -> {ok, [default_tests(State, ProjectApps)|Opts]}; + true -> {ok, Opts} end. default_tests(State, ProjectApps) -> @@ -397,14 +418,20 @@ readable(State) -> end. test_dirs(State, Apps, Opts) -> - case {proplists:get_value(suite, Opts), proplists:get_value(dir, Opts)} of - {Suites, undefined} -> set_compile_dirs(State, Apps, {suite, Suites}); - {undefined, Dirs} -> set_compile_dirs(State, Apps, {dir, Dirs}); - {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)); - {_Suites, _Dirs} -> {error, "Only a single directory may be specified when specifying suites"} + case proplists:get_value(spec, Opts) of + undefined -> + case {proplists:get_value(suite, Opts), proplists:get_value(dir, Opts)} of + {Suites, undefined} -> set_compile_dirs(State, Apps, {suite, Suites}); + {undefined, Dirs} -> set_compile_dirs(State, Apps, {dir, Dirs}); + {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)); + {_Suites, _Dirs} -> {error, "Only a single directory may be specified when specifying suites"} + end; + _Specs -> + %% Currently not adding any directories from the spec files. + {ok, rebar_state:project_apps(State, Apps)} end. join(Suite, Dir) when is_integer(hd(Suite)) -> -- cgit v1.1 From a0e7ff2eb95a8093f666d310bd5df6395a243bd8 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 8 Dec 2016 15:46:35 +0100 Subject: Add directory of testspec as extra_src_dir This is necessary in order to automatically get the testspec included as an artifact (i.e. copied to the _build dir) in the case when it is stored in another directory than 'test'. --- src/rebar_prv_common_test.erl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 5fa7ae4..17358a5 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -429,9 +429,9 @@ test_dirs(State, Apps, Opts) -> set_compile_dirs(State, Apps, join(Suites, Dir)); {_Suites, _Dirs} -> {error, "Only a single directory may be specified when specifying suites"} end; - _Specs -> - %% Currently not adding any directories from the spec files. - {ok, rebar_state:project_apps(State, Apps)} + Specs -> + set_compile_dirs(State, Apps, {spec, Specs}) + end. join(Suite, Dir) when is_integer(hd(Suite)) -> @@ -451,15 +451,15 @@ set_compile_dirs(State, Apps, {dir, Dirs}) -> F = fun(Dir, {S, A}) -> maybe_inject_test_dir(S, [], A, Dir) end, {NewState, NewApps} = lists:foldl(F, {State, Apps}, Dirs), {ok, rebar_state:project_apps(NewState, NewApps)}; -set_compile_dirs(State, Apps, {suite, Suites}) -> - %% suites with dir component - Dirs = find_suite_dirs(Suites), +set_compile_dirs(State, Apps, {Type, Files}) when Type==spec; Type==suite -> + %% specs or suites with dir component + Dirs = find_file_dirs(Files), F = fun(Dir, {S, A}) -> maybe_inject_test_dir(S, [], A, Dir) end, {NewState, NewApps} = lists:foldl(F, {State, Apps}, Dirs), {ok, rebar_state:project_apps(NewState, NewApps)}. -find_suite_dirs(Suites) -> - AllDirs = lists:map(fun(S) -> filename:dirname(filename:absname(S)) end, Suites), +find_file_dirs(Files) -> + AllDirs = lists:map(fun(F) -> filename:dirname(filename:absname(F)) end, Files), %% eliminate duplicates lists:usort(AllDirs). -- cgit v1.1 From e427a835301c41a1403cf6b9e6c363ceae3e781c Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 9 Dec 2016 14:33:43 +0100 Subject: Translate path to testspec This is a bugfix. It makes sure that the given path to a testspec is translated so common_test will pick the spec from the _build directory, and not from the source tree. --- src/rebar_prv_common_test.erl | 61 ++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 33 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 17358a5..cb33492 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -513,44 +513,39 @@ inject_test_dir(Opts, Dir) -> rebar_opts:set(Opts, extra_src_dirs, ExtraSrcDirs ++ [Dir]). translate_paths(State, Opts) -> - case {proplists:get_value(suite, Opts), proplists:get_value(dir, Opts)} of - {_Suites, undefined} -> translate_suites(State, Opts, []); - {undefined, _Dirs} -> translate_dirs(State, Opts, []); - %% both dirs and suites are defined, only translate dir paths - _ -> translate_dirs(State, Opts, []) + case proplists:get_value(spec, Opts) of + undefined -> + case {proplists:get_value(suite, Opts), proplists:get_value(dir, Opts)} of + {_Suites, undefined} -> translate_paths(State, suite, Opts, []); + {undefined, _Dirs} -> translate_paths(State, dir, Opts, []); + %% both dirs and suites are defined, only translate dir paths + _ -> translate_paths(State, dir, Opts, []) + end; + _Specs -> + translate_paths(State, spec, Opts, []) end. -translate_dirs(_State, [], Acc) -> lists:reverse(Acc); -translate_dirs(State, [{dir, Dir}|Rest], Acc) when is_integer(hd(Dir)) -> - %% single dir - Apps = rebar_state:project_apps(State), - translate_dirs(State, Rest, [{dir, translate(State, Apps, Dir)}|Acc]); -translate_dirs(State, [{dir, Dirs}|Rest], Acc) -> - %% multiple dirs - Apps = rebar_state:project_apps(State), - NewDirs = {dir, lists:map(fun(Dir) -> translate(State, Apps, Dir) end, Dirs)}, - translate_dirs(State, Rest, [NewDirs|Acc]); -translate_dirs(State, [Test|Rest], Acc) -> - translate_dirs(State, Rest, [Test|Acc]). - -translate_suites(_State, [], Acc) -> lists:reverse(Acc); -translate_suites(State, [{suite, Suite}|Rest], Acc) when is_integer(hd(Suite)) -> - %% single suite +translate_paths(_State, _Type, [], Acc) -> lists:reverse(Acc); +translate_paths(State, Type, [{Type, Val}|Rest], Acc) when is_integer(hd(Val)) -> + %% single file or dir + translate_paths(State, Type, [{Type, [Val]}|Rest], Acc); +translate_paths(State, dir, [{dir, Dirs}|Rest], Acc) -> Apps = rebar_state:project_apps(State), - translate_suites(State, Rest, [{suite, translate_suite(State, Apps, Suite)}|Acc]); -translate_suites(State, [{suite, Suites}|Rest], Acc) -> - %% multiple suites + New = {dir, lists:map(fun(Dir) -> translate(State, Apps, Dir) end, Dirs)}, + translate_paths(State, dir, Rest, [New|Acc]); +translate_paths(State, Type, [{Type, Files}|Rest], Acc) -> + %% Type = suites | specs Apps = rebar_state:project_apps(State), - NewSuites = {suite, lists:map(fun(Suite) -> translate_suite(State, Apps, Suite) end, Suites)}, - translate_suites(State, Rest, [NewSuites|Acc]); -translate_suites(State, [Test|Rest], Acc) -> - translate_suites(State, Rest, [Test|Acc]). - -translate_suite(State, Apps, Suite) -> - Dirname = filename:dirname(Suite), - Basename = filename:basename(Suite), + New = {Type, lists:map(fun(File) -> translate_file(State, Apps, File) end, Files)}, + translate_paths(State, Type, Rest, [New|Acc]); +translate_paths(State, Type, [Test|Rest], Acc) -> + translate_paths(State, Type, Rest, [Test|Acc]). + +translate_file(State, Apps, File) -> + Dirname = filename:dirname(File), + Basename = filename:basename(File), case Dirname of - "." -> Suite; + "." -> File; _ -> filename:join([translate(State, Apps, Dirname), Basename]) end. -- cgit v1.1 From a18340c6eed6e62237c4ec63f15daacfe86dc86c Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Tue, 13 Dec 2016 12:51:01 +0100 Subject: Allow using relative path to suite in project root --- src/rebar_prv_common_test.erl | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index cb33492..9db8106 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -529,26 +529,13 @@ translate_paths(_State, _Type, [], Acc) -> lists:reverse(Acc); translate_paths(State, Type, [{Type, Val}|Rest], Acc) when is_integer(hd(Val)) -> %% single file or dir translate_paths(State, Type, [{Type, [Val]}|Rest], Acc); -translate_paths(State, dir, [{dir, Dirs}|Rest], Acc) -> - Apps = rebar_state:project_apps(State), - New = {dir, lists:map(fun(Dir) -> translate(State, Apps, Dir) end, Dirs)}, - translate_paths(State, dir, Rest, [New|Acc]); translate_paths(State, Type, [{Type, Files}|Rest], Acc) -> - %% Type = suites | specs Apps = rebar_state:project_apps(State), - New = {Type, lists:map(fun(File) -> translate_file(State, Apps, File) end, Files)}, + New = {Type, lists:map(fun(File) -> translate(State, Apps, File) end, Files)}, translate_paths(State, Type, Rest, [New|Acc]); translate_paths(State, Type, [Test|Rest], Acc) -> translate_paths(State, Type, Rest, [Test|Acc]). -translate_file(State, Apps, File) -> - Dirname = filename:dirname(File), - Basename = filename:basename(File), - case Dirname of - "." -> File; - _ -> filename:join([translate(State, Apps, Dirname), Basename]) - end. - translate(State, [App|Rest], Path) -> case rebar_file_utils:path_from_ancestor(Path, rebar_app_info:dir(App)) of {ok, P} -> filename:join([rebar_app_info:out_dir(App), P]); -- cgit v1.1 From 4e52ce58e505ba57f2188e34a002d70de1bd6ff5 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Fri, 16 Dec 2016 10:34:36 +0100 Subject: Add all dirs from test spec Parse given test specs and add all spec- and suite directories as extra_src_dirs in order to ensure that all these directories are copied to the _build area and the suites are compiled. Specs located in the project- or app root are explicitly copied to the _build area in order to avoid recursive copying of the complete directory tree. --- src/rebar_prv_common_test.erl | 81 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 12 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 9db8106..4a9ba25 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -429,9 +429,18 @@ test_dirs(State, Apps, Opts) -> set_compile_dirs(State, Apps, join(Suites, Dir)); {_Suites, _Dirs} -> {error, "Only a single directory may be specified when specifying suites"} end; - Specs -> - set_compile_dirs(State, Apps, {spec, Specs}) - + Specs0 -> + case get_dirs_from_specs(Specs0) of + {ok,{Specs,SuiteDirs}} -> + {State1,Apps1} = set_compile_dirs1(State, Apps, + {dir, SuiteDirs}), + {State2,Apps2} = set_compile_dirs1(State1, Apps1, + {spec, Specs}), + [maybe_copy_spec(State2,Apps2,S) || S <- Specs], + {ok, rebar_state:project_apps(State2, Apps2)}; + Error -> + Error + end end. join(Suite, Dir) when is_integer(hd(Suite)) -> @@ -439,24 +448,25 @@ join(Suite, Dir) when is_integer(hd(Suite)) -> join(Suites, Dir) -> {suite, lists:map(fun(S) -> filename:join([Dir, S]) end, Suites)}. -set_compile_dirs(State, Apps, {dir, Dir}) when is_integer(hd(Dir)) -> +set_compile_dirs(State, Apps, What) -> + {NewState,NewApps} = set_compile_dirs1(State, Apps, What), + {ok, rebar_state:project_apps(NewState, NewApps)}. + +set_compile_dirs1(State, Apps, {dir, Dir}) when is_integer(hd(Dir)) -> %% single directory %% insert `Dir` into an app if relative, or the base state if not %% app relative but relative to the root or not at all if outside %% project scope - {NewState, NewApps} = maybe_inject_test_dir(State, [], Apps, Dir), - {ok, rebar_state:project_apps(NewState, NewApps)}; -set_compile_dirs(State, Apps, {dir, Dirs}) -> + maybe_inject_test_dir(State, [], Apps, Dir); +set_compile_dirs1(State, Apps, {dir, Dirs}) -> %% multiple directories F = fun(Dir, {S, A}) -> maybe_inject_test_dir(S, [], A, Dir) end, - {NewState, NewApps} = lists:foldl(F, {State, Apps}, Dirs), - {ok, rebar_state:project_apps(NewState, NewApps)}; -set_compile_dirs(State, Apps, {Type, Files}) when Type==spec; Type==suite -> + lists:foldl(F, {State, Apps}, Dirs); +set_compile_dirs1(State, Apps, {Type, Files}) when Type==spec; Type==suite -> %% specs or suites with dir component Dirs = find_file_dirs(Files), F = fun(Dir, {S, A}) -> maybe_inject_test_dir(S, [], A, Dir) end, - {NewState, NewApps} = lists:foldl(F, {State, Apps}, Dirs), - {ok, rebar_state:project_apps(NewState, NewApps)}. + lists:foldl(F, {State, Apps}, Dirs). find_file_dirs(Files) -> AllDirs = lists:map(fun(F) -> filename:dirname(filename:absname(F)) end, Files), @@ -507,11 +517,58 @@ copy_bare_suites(From, To) -> ok = rebar_file_utils:cp_r(SrcFiles, To), rebar_file_utils:cp_r(DataDirs, To). +maybe_copy_spec(State, [App|Apps], Spec) -> + case rebar_file_utils:path_from_ancestor(filename:dirname(Spec), rebar_app_info:dir(App)) of + {ok, []} -> + ok = rebar_file_utils:cp_r([Spec],rebar_app_info:out_dir(App)); + {ok,_} -> + ok; + {error,badparent} -> + maybe_copy_spec(State, Apps, Spec) + end; +maybe_copy_spec(State, [], Spec) -> + case rebar_file_utils:path_from_ancestor(filename:dirname(Spec), rebar_state:dir(State)) of + {ok, []} -> + ExtrasDir = filename:join([rebar_dir:base_dir(State), "extras"]), + ok = rebar_file_utils:cp_r([Spec],ExtrasDir); + _R -> + ok + end. + inject_test_dir(Opts, Dir) -> %% append specified test targets to app defined `extra_src_dirs` ExtraSrcDirs = rebar_opts:get(Opts, extra_src_dirs, []), rebar_opts:set(Opts, extra_src_dirs, ExtraSrcDirs ++ [Dir]). +get_dirs_from_specs(Specs) -> + case get_tests_from_specs(Specs) of + {ok,Tests} -> + {SpecLists,NodeRunSkipLists} = lists:unzip(Tests), + SpecList = lists:append(SpecLists), + NodeRunSkipList = lists:append(NodeRunSkipLists), + RunList = lists:append([R || {_,R,_} <- NodeRunSkipList]), + DirList = [element(1,R) || R <- RunList], + {ok,{SpecList,DirList}}; + Error -> + Error + end. + +get_tests_from_specs(Specs) -> + case erlang:function_exported(ct_testspec,get_tests,1) of + true -> + ct_testspec:get_tests(Specs); + false -> + case ct_testspec:collect_tests_from_file(Specs,true) of + Tests when is_list(Tests) -> + {ok,[{S,ct_testspec:prepare_tests(R)} || {S,R} <- Tests]}; + R when is_tuple(R), element(1,R)==testspec -> + %% R15 + {ok,[{Specs,ct_testspec:prepare_tests(R)}]}; + Error -> + Error + end + end. + translate_paths(State, Opts) -> case proplists:get_value(spec, Opts) of undefined -> -- cgit v1.1 From 998c6756b73ec2c227ed6f7f2e66eb059d1027fc Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 22 Dec 2016 20:25:52 +0100 Subject: Make sure ct_testspec is loaded ... before calling erlang:function_exported(ct_testspec,get_tests,1). --- src/rebar_prv_common_test.erl | 1 + 1 file changed, 1 insertion(+) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 4a9ba25..30596da 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -554,6 +554,7 @@ get_dirs_from_specs(Specs) -> end. get_tests_from_specs(Specs) -> + _ = ct_testspec:module_info(), % make sure ct_testspec is loaded case erlang:function_exported(ct_testspec,get_tests,1) of true -> ct_testspec:get_tests(Specs); -- cgit v1.1 From 146f2732b96b5db6476e3b86b13e7a3d7b1b2dc5 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 22 Dec 2016 22:14:07 +0100 Subject: Handle errors from ct_testspec --- src/rebar_prv_common_test.erl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 30596da..2ac8fc7 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -100,7 +100,9 @@ format_error({badconfig, Msg}) -> io_lib:format(Msg, []); format_error({multiple_errors, Errors}) -> io_lib:format(lists:concat(["Error running tests:"] ++ - lists:map(fun(Error) -> "~n " ++ Error end, Errors)), []). + lists:map(fun(Error) -> "~n " ++ Error end, Errors)), []); +format_error({error_reading_testspec, Reason}) -> + io_lib:format("Error reading testspec: ~p", [Reason]). %% =================================================================== %% Internal functions @@ -549,8 +551,8 @@ get_dirs_from_specs(Specs) -> RunList = lists:append([R || {_,R,_} <- NodeRunSkipList]), DirList = [element(1,R) || R <- RunList], {ok,{SpecList,DirList}}; - Error -> - Error + {error,Reason} -> + {error,{?MODULE,{error_reading_testspec,Reason}}} end. get_tests_from_specs(Specs) -> -- cgit v1.1 From 64b5d878af4839ac7e2514bdc497cce818b1755e Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 6 Mar 2017 11:36:26 +0100 Subject: Allow single test spec in ct_opts The option {spec,Specs} is allowed in ct_opts, but rebar_prv_common_test:test_dirs did not take into account that Specs could also be a string only, i.e. not a list of strings. --- src/rebar_prv_common_test.erl | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 2ac8fc7..7a060f8 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -431,18 +431,21 @@ test_dirs(State, Apps, Opts) -> set_compile_dirs(State, Apps, join(Suites, Dir)); {_Suites, _Dirs} -> {error, "Only a single directory may be specified when specifying suites"} end; - Specs0 -> - case get_dirs_from_specs(Specs0) of - {ok,{Specs,SuiteDirs}} -> - {State1,Apps1} = set_compile_dirs1(State, Apps, - {dir, SuiteDirs}), - {State2,Apps2} = set_compile_dirs1(State1, Apps1, - {spec, Specs}), - [maybe_copy_spec(State2,Apps2,S) || S <- Specs], - {ok, rebar_state:project_apps(State2, Apps2)}; - Error -> - Error - end + Spec when is_integer(hd(Spec)) -> + spec_test_dirs(State, Apps, [Spec]); + Specs -> + spec_test_dirs(State, Apps, Specs) + end. + +spec_test_dirs(State, Apps, Specs0) -> + case get_dirs_from_specs(Specs0) of + {ok,{Specs,SuiteDirs}} -> + {State1,Apps1} = set_compile_dirs1(State, Apps, {dir, SuiteDirs}), + {State2,Apps2} = set_compile_dirs1(State1, Apps1, {spec, Specs}), + [maybe_copy_spec(State2,Apps2,S) || S <- Specs], + {ok, rebar_state:project_apps(State2, Apps2)}; + Error -> + Error end. join(Suite, Dir) when is_integer(hd(Suite)) -> -- cgit v1.1 From e83100bbc85967134fe68dbf691c2cca8d6db10c Mon Sep 17 00:00:00 2001 From: Michiel Beijen Date: Mon, 27 Mar 2017 21:26:23 +0200 Subject: Typo: seperate -> separate --- src/rebar_prv_common_test.erl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 7a060f8..bbd2a11 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -708,17 +708,17 @@ maybe_write_coverdata(State) -> rebar_prv_cover:maybe_write_coverdata(State1, ?PROVIDER). ct_opts(_State) -> - [{dir, undefined, "dir", string, help(dir)}, %% comma-seperated list - {suite, undefined, "suite", string, help(suite)}, %% comma-seperated list - {group, undefined, "group", string, help(group)}, %% comma-seperated list - {testcase, undefined, "case", string, help(testcase)}, %% comma-seperated list + [{dir, undefined, "dir", string, help(dir)}, %% comma-separated list + {suite, undefined, "suite", string, help(suite)}, %% comma-separated list + {group, undefined, "group", string, help(group)}, %% comma-separated list + {testcase, undefined, "case", string, help(testcase)}, %% comma-separated list {label, undefined, "label", string, help(label)}, %% String - {config, undefined, "config", string, help(config)}, %% comma-seperated list - {spec, undefined, "spec", string, help(spec)}, %% comma-seperated list + {config, undefined, "config", string, help(config)}, %% comma-separated list + {spec, undefined, "spec", string, help(spec)}, %% comma-separated list {join_specs, undefined, "join_specs", boolean, help(join_specs)}, {allow_user_terms, undefined, "allow_user_terms", boolean, help(allow_user_terms)}, %% Bool {logdir, undefined, "logdir", string, help(logdir)}, %% dir - {logopts, undefined, "logopts", string, help(logopts)}, %% comma seperated list + {logopts, undefined, "logopts", string, help(logopts)}, %% comma-separated list {verbosity, undefined, "verbosity", integer, help(verbosity)}, %% Integer {cover, $c, "cover", {boolean, false}, help(cover)}, {repeat, undefined, "repeat", integer, help(repeat)}, %% integer @@ -739,7 +739,7 @@ ct_opts(_State) -> {name, undefined, "name", atom, help(name)}, {sname, undefined, "sname", atom, help(sname)}, {setcookie, undefined, "setcookie", atom, help(setcookie)}, - {sys_config, undefined, "sys_config", string, help(sys_config)} %% comma-seperated list + {sys_config, undefined, "sys_config", string, help(sys_config)} %% comma-separated list ]. help(dir) -> -- cgit v1.1 From d15ea91b714c56c2d94996f3f5138edd062e5a5d Mon Sep 17 00:00:00 2001 From: Luis Rascao Date: Wed, 5 Apr 2017 14:13:22 +0100 Subject: Fix typo, occured -> occurred --- src/rebar_prv_common_test.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index bbd2a11..62dd9f1 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -93,7 +93,7 @@ format_error({error, Reason}) -> format_error({error_running_tests, Reason}) -> format_error({error, Reason}); format_error({failures_running_tests, {Failed, AutoSkipped}}) -> - io_lib:format("Failures occured running tests: ~b", [Failed+AutoSkipped]); + io_lib:format("Failures occurred running tests: ~b", [Failed+AutoSkipped]); format_error({badconfig, {Msg, {Value, Key}}}) -> io_lib:format(Msg, [Value, Key]); format_error({badconfig, Msg}) -> -- cgit v1.1 From 1f9404e9cd5edc44627a17204c9ba01b32487dae Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Wed, 3 May 2017 08:36:11 -0400 Subject: Drop R15 support It can't even fetch packages from Hex anymore because of old SSL/TLS libraries, and so it can't bootstrap anymore either. Plus R20 comes out soon, and 5 major versions is quite enough. --- src/rebar_prv_common_test.erl | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 62dd9f1..e6788f8 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -567,9 +567,6 @@ get_tests_from_specs(Specs) -> case ct_testspec:collect_tests_from_file(Specs,true) of Tests when is_list(Tests) -> {ok,[{S,ct_testspec:prepare_tests(R)} || {S,R} <- Tests]}; - R when is_tuple(R), element(1,R)==testspec -> - %% R15 - {ok,[{Specs,ct_testspec:prepare_tests(R)}]}; Error -> Error end -- cgit v1.1 From f4ca27d58fa81521808f530cfa50b9b314e93aa2 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 11 May 2017 08:27:39 -0400 Subject: Handle internal CT failures This is based on issue #1517 where out of nowhere, CT has returned a user's error code directly. This in turn caused a crashdump in rebar3 itself. This patch handles the unexpected cases by: a) not trying to format them b) converting them to an error whenever they happen The execution flow is still interrupted, but we should fail with a clearer error than a crashdump. --- src/rebar_prv_common_test.erl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index e6788f8..3df8b75 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -650,7 +650,11 @@ handle_results(_) -> sum_results({Passed, Failed, {UserSkipped, AutoSkipped}}, {Passed2, Failed2, {UserSkipped2, AutoSkipped2}}) -> {Passed+Passed2, Failed+Failed2, - {UserSkipped+UserSkipped2, AutoSkipped+AutoSkipped2}}. + {UserSkipped+UserSkipped2, AutoSkipped+AutoSkipped2}}; +sum_results(_, {error, Reason}) -> + {error, Reason}; +sum_results(Unknown, _) -> + {error, Unknown}. handle_quiet_results(_, {error, _} = Result) -> handle_results(Result); @@ -673,7 +677,10 @@ format_result({Passed, 0, {0, 0}}) -> format_result({Passed, Failed, Skipped}) -> Format = [format_failed(Failed), format_skipped(Skipped), format_passed(Passed)], - ?CONSOLE("~s", [Format]). + ?CONSOLE("~s", [Format]); +format_result(_Unknown) -> + %% Happens when CT itself encounters a bug + ok. format_failed(0) -> []; -- cgit v1.1 From 15461c9b1edf77ef91cc70b0db9c824bda876642 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Thu, 13 Jul 2017 18:13:16 -0700 Subject: add compile_only option to ct provider --- src/rebar_prv_common_test.erl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 3df8b75..dfade77 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -41,7 +41,14 @@ do(State) -> Tests = prepare_tests(State), case compile(State, Tests) of %% successfully compiled apps - {ok, S} -> do(S, Tests); + {ok, S} -> + {RawOpts, _} = rebar_state:command_parsed_args(S), + case proplists:get_value(compile_only, RawOpts, false) of + true -> + {ok, S}; + false -> + do(S, Tests) + end; %% this should look like a compiler error, not a ct error Error -> Error end. @@ -743,9 +750,12 @@ ct_opts(_State) -> {name, undefined, "name", atom, help(name)}, {sname, undefined, "sname", atom, help(sname)}, {setcookie, undefined, "setcookie", atom, help(setcookie)}, - {sys_config, undefined, "sys_config", string, help(sys_config)} %% comma-separated list + {sys_config, undefined, "sys_config", string, help(sys_config)}, %% comma-separated list + {compile_only, undefined, "compile_only", boolean, help(compile_only)} ]. +help(compile_only) -> + "Compile modules in the project with the test configuration but do not run the tests"; help(dir) -> "List of additional directories containing test suites"; help(suite) -> -- cgit v1.1 From 963c49f5eb9ab5b34e1843fb43305743720917ac Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sun, 6 Aug 2017 07:26:21 -0400 Subject: Unicode support in all the places This is done through 3 main change groups: - replacing `~s` by `~ts` in format strings, so that strings that contain unicode are properly printed rather than crashing - adding the `unicode` argument to all function of the `re` module to ensure transformations on strings containing unicode data are valid instead of crashing (see issue #1302) - replacing `ec_cnv:to_binary/1` and `ec_cnv:to_list/1` with matching functions in `rebar_utils`. The last point has been done, rather than modifying and updating erlware commons, because binary and list conversions can be a contentious subject. For example, if what is being handled is actually bytes from a given binary stream, then forcing a byte-oriented interpretation of the data can corrupt it. As such, it does not appear safe to modify erlware commons' conversion functions since it may not be safe for all its users. Instead, rebar3 reimplements a subset of them (only converting atoms and chardata, ignoring numbers) with the explicit purpose of handling unicode string data. Tests were left as unchanged as possible. This may impact the ability to run rebar3's own suites in a unicode path, but respects a principle of least change for such a large patch. --- src/rebar_prv_common_test.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index dfade77..bf788d2 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -684,7 +684,7 @@ format_result({Passed, 0, {0, 0}}) -> format_result({Passed, Failed, Skipped}) -> Format = [format_failed(Failed), format_skipped(Skipped), format_passed(Passed)], - ?CONSOLE("~s", [Format]); + ?CONSOLE("~ts", [Format]); format_result(_Unknown) -> %% Happens when CT itself encounters a bug ok. -- cgit v1.1 From 2d5cd9c00cfa4e58066b48beee4057fdd52cc7be Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Wed, 1 Nov 2017 19:38:03 -0400 Subject: OTP-21 readiness, Full Unicode support This replaces all deprecated function usage by alternative ones based on a version switch enacted at compile time, preventing all warnings. This will likely introduce some possible runtime errors in using a Rebar3 compiled on OTP-20 or OTP-21 back in versions 19 and earlier, but we can't really work around that. A bunch of dependencies have been updated to support OTP-21 without warnings as well. --- src/rebar_prv_common_test.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index bf788d2..2443710 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -173,7 +173,7 @@ transform_opts([Opt|Rest], Acc) -> transform_opts(Rest, [Opt|Acc]). split_string(String) -> - string:tokens(String, [$,]). + rebar_string:lexemes(String, [$,]). cfgopts(State) -> case rebar_state:get(State, ct_opts, []) of -- cgit v1.1 From 38bbbafb7e2546e301d027ab67b587882cf333c2 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 23 Nov 2017 13:52:38 -0500 Subject: Add experimental support for ct --retry option This commit adds a common test hook along with the cth_readable stuff whose role is to track failing test cases, and create a test specification out of them. The test specification is dumped on disk at _build//logs/retry.spec and can be accessed by calling 'rebar3 ct --retry'. This will auto-load the spec file if it can be found and re-run the failing cases. If any other argument is found on the list specifying tests, the '--retry' argument is ignored. All code for this is marked as experimental in case we end up (keeping and then) dropping the feature. --- src/rebar_prv_common_test.erl | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 2443710..a88753c 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -213,10 +213,10 @@ add_hooks(Opts, State) -> {false, _} -> Opts; {true, false} -> - [{ct_hooks, [cth_readable_failonly, cth_readable_shell]} | Opts]; + [{ct_hooks, [cth_readable_failonly, cth_readable_shell, cth_retry]} | Opts]; {true, {ct_hooks, Hooks}} -> %% Make sure hooks are there once only. - ReadableHooks = [cth_readable_failonly, cth_readable_shell], + ReadableHooks = [cth_readable_failonly, cth_readable_shell, cth_retry], NewHooks = (Hooks -- ReadableHooks) ++ ReadableHooks, lists:keyreplace(ct_hooks, 1, Opts, {ct_hooks, NewHooks}) end. @@ -272,6 +272,15 @@ is_any_defined([Key|Keys],Opts) -> is_any_defined([],_Opts) -> false. +should_retry(State, Opts) -> + case proplists:get_value(retry, Opts, false) of + false -> + false; + true -> + Path = filename:join([rebar_dir:base_dir(State), "logs", "retry.spec"]), + filelib:is_file(Path) andalso {true, Path} + end. + sys_config_list(CmdOpts, CfgOpts) -> CmdSysConfigs = split_string(proplists:get_value(sys_config, CmdOpts, "")), case proplists:get_value(sys_config, CfgOpts, []) of @@ -285,9 +294,15 @@ sys_config_list(CmdOpts, CfgOpts) -> discover_tests(State, ProjectApps, Opts) -> case is_any_defined([spec,dir,suite],Opts) of + true -> {ok, Opts}; %% no tests defined, try using `$APP/test` and `$ROOT/test` as dirs - false -> {ok, [default_tests(State, ProjectApps)|Opts]}; - true -> {ok, Opts} + false -> + case should_retry(State, Opts) of + false -> + {ok, [default_tests(State, ProjectApps)|Opts]}; + {true, Path} -> + {ok, [{spec, Path} | Opts]} + end end. default_tests(State, ProjectApps) -> @@ -751,7 +766,8 @@ ct_opts(_State) -> {sname, undefined, "sname", atom, help(sname)}, {setcookie, undefined, "setcookie", atom, help(setcookie)}, {sys_config, undefined, "sys_config", string, help(sys_config)}, %% comma-separated list - {compile_only, undefined, "compile_only", boolean, help(compile_only)} + {compile_only, undefined, "compile_only", boolean, help(compile_only)}, + {retry, undefined, "retry", boolean, help(retry)} ]. help(compile_only) -> @@ -820,5 +836,7 @@ help(sname) -> "Gives a short name to the node"; help(setcookie) -> "Sets the cookie if the node is distributed"; +help(retry) -> + "Experimental feature. If any specification for previously failing test is found, runs them."; help(_) -> "". -- cgit v1.1 From 26136b6b54e95d3832c1ffe2f8bbab642c01ba1d Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 24 Nov 2017 14:27:02 -0500 Subject: Revert "Add experimental support for ct --retry option" --- src/rebar_prv_common_test.erl | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index a88753c..2443710 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -213,10 +213,10 @@ add_hooks(Opts, State) -> {false, _} -> Opts; {true, false} -> - [{ct_hooks, [cth_readable_failonly, cth_readable_shell, cth_retry]} | Opts]; + [{ct_hooks, [cth_readable_failonly, cth_readable_shell]} | Opts]; {true, {ct_hooks, Hooks}} -> %% Make sure hooks are there once only. - ReadableHooks = [cth_readable_failonly, cth_readable_shell, cth_retry], + ReadableHooks = [cth_readable_failonly, cth_readable_shell], NewHooks = (Hooks -- ReadableHooks) ++ ReadableHooks, lists:keyreplace(ct_hooks, 1, Opts, {ct_hooks, NewHooks}) end. @@ -272,15 +272,6 @@ is_any_defined([Key|Keys],Opts) -> is_any_defined([],_Opts) -> false. -should_retry(State, Opts) -> - case proplists:get_value(retry, Opts, false) of - false -> - false; - true -> - Path = filename:join([rebar_dir:base_dir(State), "logs", "retry.spec"]), - filelib:is_file(Path) andalso {true, Path} - end. - sys_config_list(CmdOpts, CfgOpts) -> CmdSysConfigs = split_string(proplists:get_value(sys_config, CmdOpts, "")), case proplists:get_value(sys_config, CfgOpts, []) of @@ -294,15 +285,9 @@ sys_config_list(CmdOpts, CfgOpts) -> discover_tests(State, ProjectApps, Opts) -> case is_any_defined([spec,dir,suite],Opts) of - true -> {ok, Opts}; %% no tests defined, try using `$APP/test` and `$ROOT/test` as dirs - false -> - case should_retry(State, Opts) of - false -> - {ok, [default_tests(State, ProjectApps)|Opts]}; - {true, Path} -> - {ok, [{spec, Path} | Opts]} - end + false -> {ok, [default_tests(State, ProjectApps)|Opts]}; + true -> {ok, Opts} end. default_tests(State, ProjectApps) -> @@ -766,8 +751,7 @@ ct_opts(_State) -> {sname, undefined, "sname", atom, help(sname)}, {setcookie, undefined, "setcookie", atom, help(setcookie)}, {sys_config, undefined, "sys_config", string, help(sys_config)}, %% comma-separated list - {compile_only, undefined, "compile_only", boolean, help(compile_only)}, - {retry, undefined, "retry", boolean, help(retry)} + {compile_only, undefined, "compile_only", boolean, help(compile_only)} ]. help(compile_only) -> @@ -836,7 +820,5 @@ help(sname) -> "Gives a short name to the node"; help(setcookie) -> "Sets the cookie if the node is distributed"; -help(retry) -> - "Experimental feature. If any specification for previously failing test is found, runs them."; help(_) -> "". -- cgit v1.1 From 32ae99650110637d479bb0db64dc1e6583d7b094 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 23 Nov 2017 13:52:38 -0500 Subject: Add experimental support for ct --retry option This commit adds a common test hook along with the cth_readable stuff whose role is to track failing test cases, and create a test specification out of them. The test specification is dumped on disk at _build//logs/retry.spec and can be accessed by calling 'rebar3 ct --retry'. This will auto-load the spec file if it can be found and re-run the failing cases. If any other argument is found on the list specifying tests, the '--retry' argument is ignored. All code for this is marked as experimental in case we end up (keeping and then) dropping the feature. --- src/rebar_prv_common_test.erl | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 2443710..9631a0d 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -135,7 +135,7 @@ cmdopts(State) -> {RawOpts, _} = rebar_state:command_parsed_args(State), %% filter out opts common_test doesn't know about and convert %% to ct acceptable forms - transform_opts(RawOpts, []). + transform_retry(transform_opts(RawOpts, []), State). transform_opts([], Acc) -> lists:reverse(Acc); transform_opts([{dir, Dirs}|Rest], Acc) -> @@ -172,6 +172,18 @@ transform_opts([{verbose, _}|Rest], Acc) -> transform_opts([Opt|Rest], Acc) -> transform_opts(Rest, [Opt|Acc]). +%% @private only retry if specified and if no other spec +%% is given. +transform_retry(Opts, State) -> + case proplists:get_value(retry, Opts, false) andalso + not is_any_defined([spec,dir,suite], Opts) of + false -> + Opts; + true -> + Path = filename:join([rebar_dir:base_dir(State), "logs", "retry.spec"]), + filelib:is_file(Path) andalso [{spec, Path}|Opts] + end. + split_string(String) -> rebar_string:lexemes(String, [$,]). @@ -213,10 +225,10 @@ add_hooks(Opts, State) -> {false, _} -> Opts; {true, false} -> - [{ct_hooks, [cth_readable_failonly, cth_readable_shell]} | Opts]; + [{ct_hooks, [cth_readable_failonly, cth_readable_shell, cth_retry]} | Opts]; {true, {ct_hooks, Hooks}} -> %% Make sure hooks are there once only. - ReadableHooks = [cth_readable_failonly, cth_readable_shell], + ReadableHooks = [cth_readable_failonly, cth_readable_shell, cth_retry], NewHooks = (Hooks -- ReadableHooks) ++ ReadableHooks, lists:keyreplace(ct_hooks, 1, Opts, {ct_hooks, NewHooks}) end. @@ -751,7 +763,8 @@ ct_opts(_State) -> {sname, undefined, "sname", atom, help(sname)}, {setcookie, undefined, "setcookie", atom, help(setcookie)}, {sys_config, undefined, "sys_config", string, help(sys_config)}, %% comma-separated list - {compile_only, undefined, "compile_only", boolean, help(compile_only)} + {compile_only, undefined, "compile_only", boolean, help(compile_only)}, + {retry, undefined, "retry", boolean, help(retry)} ]. help(compile_only) -> @@ -820,5 +833,7 @@ help(sname) -> "Gives a short name to the node"; help(setcookie) -> "Sets the cookie if the node is distributed"; +help(retry) -> + "Experimental feature. If any specification for previously failing test is found, runs them."; help(_) -> "". -- cgit v1.1 From 72b649cc664747d7682eec7150f6ad022b3838ae Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Mon, 4 Dec 2017 11:35:22 -0800 Subject: add eunit and ct option to set coverdata file name --- src/rebar_prv_common_test.erl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 9631a0d..f800610 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -8,8 +8,11 @@ -export([init/1, do/1, format_error/1]). -%% exported for test purposes, consider private --export([compile/2, prepare_tests/1, translate_paths/2]). + +-ifdef(TEST). +%% exported for test purposes +-export([compile/2, prepare_tests/1, translate_paths/2, maybe_write_coverdata/1]). +-endif. -include("rebar.hrl"). -include_lib("providers/include/providers.hrl"). @@ -728,7 +731,8 @@ maybe_write_coverdata(State) -> true -> rebar_state:set(State, cover_enabled, true); false -> State end, - rebar_prv_cover:maybe_write_coverdata(State1, ?PROVIDER). + Name = proplists:get_value(cover_export_name, RawOpts, ?PROVIDER), + rebar_prv_cover:maybe_write_coverdata(State1, Name). ct_opts(_State) -> [{dir, undefined, "dir", string, help(dir)}, %% comma-separated list @@ -744,6 +748,7 @@ ct_opts(_State) -> {logopts, undefined, "logopts", string, help(logopts)}, %% comma-separated list {verbosity, undefined, "verbosity", integer, help(verbosity)}, %% Integer {cover, $c, "cover", {boolean, false}, help(cover)}, + {cover_export_name, undefined, "cover_export_name", string, help(cover_export_name)}, {repeat, undefined, "repeat", integer, help(repeat)}, %% integer {duration, undefined, "duration", string, help(duration)}, % format: HHMMSS {until, undefined, "until", string, help(until)}, %% format: YYMoMoDD[HHMMSS] @@ -797,6 +802,8 @@ help(verbosity) -> "Verbosity"; help(cover) -> "Generate cover data"; +help(cover_export_name) -> + "Base name of the coverdata file to write"; help(repeat) -> "How often to repeat tests"; help(duration) -> -- cgit v1.1 From 254bb7be7c91aed2799061094c571b041038b5fb Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Sat, 5 May 2018 10:39:25 -0400 Subject: Logger support in cth_readable; compact CT output cth_readable 1.4.0 supports the new logger interface from OTP-21, which likely breaks compatibility with R16 builds. It also includes a new compact interface, displaying output such as: ===> Running Common Test suites... %%% rebar_alias_SUITE: ...... %%% rebar_as_SUITE: ........... %%% rebar_compile_SUITE:................................ ............................ %%% rebar_compile_SUITE ==> test_name: SKIPPED %%% rebar_compile_SUITE ==> {tc_user_skip,"compile:env_compiler_options/0 available"} .. %%% rebar_cover_SUITE: ............. %%% rebar_ct_SUITE: .................................... Allowing to display more tests within less screen space. This mode has been added to the ct_readable option under the name 'compact' (now supporting true | false | compact), and has been made default for rebar3. --- src/rebar_prv_common_test.erl | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index f800610..9e71ee7 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -227,15 +227,20 @@ add_hooks(Opts, State) -> case {readable(State), lists:keyfind(ct_hooks, 1, Opts)} of {false, _} -> Opts; - {true, false} -> - [{ct_hooks, [cth_readable_failonly, cth_readable_shell, cth_retry]} | Opts]; - {true, {ct_hooks, Hooks}} -> + {Other, false} -> + [{ct_hooks, [cth_readable_failonly, readable_shell_type(Other), cth_retry]} | Opts]; + {Other, {ct_hooks, Hooks}} -> %% Make sure hooks are there once only. - ReadableHooks = [cth_readable_failonly, cth_readable_shell, cth_retry], - NewHooks = (Hooks -- ReadableHooks) ++ ReadableHooks, + ReadableHooks = [cth_readable_failonly, readable_shell_type(Other), cth_retry], + AllReadableHooks = [cth_readable_failonly, cth_retry, + cth_readable_shell, cth_readable_compact_shell], + NewHooks = (Hooks -- AllReadableHooks) ++ ReadableHooks, lists:keyreplace(ct_hooks, 1, Opts, {ct_hooks, NewHooks}) end. +readable_shell_type(true) -> cth_readable_shell; +readable_shell_type(compact) -> cth_readable_compact_shell. + select_tests(_, _, _, {error, _} = Error) -> Error; select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> %% set application env if sys_config argument is provided @@ -425,20 +430,21 @@ append(A, B) -> A ++ B. add_transforms(CTOpts, State) when is_list(CTOpts) -> case readable(State) of - true -> - ReadableTransform = [{parse_transform, cth_readable_transform}], - (CTOpts -- ReadableTransform) ++ ReadableTransform; false -> - CTOpts + CTOpts; + Other when Other == true; Other == compact -> + ReadableTransform = [{parse_transform, cth_readable_transform}], + (CTOpts -- ReadableTransform) ++ ReadableTransform end; add_transforms({error, _} = Error, _State) -> Error. readable(State) -> {RawOpts, _} = rebar_state:command_parsed_args(State), case proplists:get_value(readable, RawOpts) of - true -> true; - false -> false; - undefined -> rebar_state:get(State, ct_readable, true) + "true" -> true; + "false" -> false; + "compact" -> compact; + undefined -> rebar_state:get(State, ct_readable, compact) end. test_dirs(State, Apps, Opts) -> @@ -762,7 +768,7 @@ ct_opts(_State) -> {scale_timetraps, undefined, "scale_timetraps", boolean, help(scale_timetraps)}, {create_priv_dir, undefined, "create_priv_dir", string, help(create_priv_dir)}, {include, undefined, "include", string, help(include)}, - {readable, undefined, "readable", boolean, help(readable)}, + {readable, undefined, "readable", string, help(readable)}, {verbose, $v, "verbose", boolean, help(verbose)}, {name, undefined, "name", atom, help(name)}, {sname, undefined, "sname", atom, help(sname)}, @@ -831,7 +837,7 @@ help(create_priv_dir) -> help(include) -> "Directories containing additional include files"; help(readable) -> - "Shows test case names and only displays logs to shell on failures"; + "Shows test case names and only displays logs to shell on failures (true | compact | false)"; help(verbose) -> "Verbose output"; help(name) -> -- cgit v1.1 From 9d788d893620f868b9c0ee00ddec8ae4d5d8fea7 Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Fri, 5 Oct 2018 07:57:20 -0400 Subject: Abstracted path management Move path management out of rebar_utils manual code path function handling (which we leave there for backwards compat), and centralize them to allow easier coordination of paths between plugins and deps. On top of path handling, do a check of loaded modules to only purge and reload those that actually need it done in order to prevent all kinds of weird interaction and accidental purge kills. It also allows the possible cohabitation of both at once, with a "in case of conflict pick X" as a policy Changing path handling in providers also highlighted a bunch of bugs in some tests and appears to fix some in other providers, specifically around plugins. --- src/rebar_prv_common_test.erl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src/rebar_prv_common_test.erl') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 9e71ee7..3d3bd8a 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -58,7 +58,7 @@ do(State) -> do(State, Tests) -> ?INFO("Running Common Test suites...", []), - rebar_utils:update_code(rebar_state:code_paths(State, all_deps), [soft_purge]), + rebar_paths:set_paths([deps, plugins], State), %% Run ct provider prehooks Providers = rebar_state:providers(State), @@ -73,14 +73,14 @@ do(State, Tests) -> ok -> %% Run ct provider post hooks for all project apps and top level project hooks rebar_hooks:run_project_and_app_hooks(Cwd, post, ?PROVIDER, Providers, State), - rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)), + rebar_paths:set_paths([plugins, deps], State), {ok, State}; Error -> - rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)), + rebar_paths:set_paths([plugins, deps], State), Error end; Error -> - rebar_utils:cleanup_code_path(rebar_state:code_paths(State, default)), + rebar_paths:set_paths([plugins, deps], State), Error end. @@ -250,11 +250,9 @@ select_tests(State, ProjectApps, CmdOpts, CfgOpts) -> end, SysConfigs), %% NB: load the applications (from user directories too) to support OTP < 17 %% to our best ability. - OldPath = code:get_path(), - code:add_pathsa(rebar_state:code_paths(State, all_deps)), + rebar_paths:set_paths([deps, plugins], State), [application:load(Application) || Config <- Configs, {Application, _} <- Config], rebar_utils:reread_config(Configs), - code:set_path(OldPath), Opts = merge_opts(CmdOpts,CfgOpts), discover_tests(State, ProjectApps, Opts). -- cgit v1.1