From 94e474e471276171cc9bfeaf4edef73b7c10a29c Mon Sep 17 00:00:00 2001 From: omarkj Date: Tue, 25 Nov 2014 21:17:36 -0800 Subject: Validate the input as it comes in from the command line by converting things to atoms and splitting up strings where needed. --- src/rebar_prv_common_test.erl | 135 +++++++++++++++++++++++++++++------------- 1 file changed, 95 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index c2d023b..2e847a2 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -33,9 +33,11 @@ init(State) -> -spec do(rebar_state:t()) -> {ok, rebar_state:t()}. do(State) -> - Opts = build_options(State), + {Opts, _} = rebar_state:command_parsed_args(State), + Opts1 = transform_opts(Opts), + ok = create_dirs(Opts1), expand_test_deps(filename:absname(rebar_state:get(State, test_deps_dir, ?DEFAULT_TEST_DEPS_DIR))), - ct:run_test(Opts), + ct:run_test(Opts1), {ok, State}. -spec format_error(any()) -> iolist(). @@ -68,7 +70,7 @@ ct_opts(State) -> {cover, undefined, "cover", string, help(cover)}, %% file {cover_stop, undefined, "cover_stop", boolean, help(cover_stop)}, %% Boolean {event_handler, undefined, "event_handler", string, help(event_handler)}, %% EH | [EH] WHERE EH atom() | {atom(), InitArgs} | {[atom()], InitArgs} - {include, undefined, "include", string, help(include)}, + {include, undefined, "include", string, help(include)}, % comma-seperated list {abort_if_missing_suites, undefined, "abort_if_missing_suites", {boolean, true}, help(abort_if_missing_suites)}, %% boolean {multiply_timetraps, undefined, "multiply_timetraps", integer, @@ -83,6 +85,96 @@ ct_opts(State) -> {ct_hooks, undefined, "ct_hooks", string, help(ct_hooks)} %% List: [CTHModule | {CTHModule, CTHInitArgs}] where CTHModule is atom CthInitArgs is term ]. +transform_opts(Opts) -> + transform_opts(Opts, []). + +transform_opts([], Acc) -> Acc; +transform_opts([{ct_hooks, CtHooks}|Rest], Acc) -> + transform_opts(Rest, [{ct_hooks, parse_term(CtHooks)}|Acc]); +transform_opts([{force_stop, "skip_rest"}|Rest], Acc) -> + transform_opts(Rest, [{force_stop, skip_rest}|Acc]); +transform_opts([{force_stop, _}|Rest], Acc) -> + transform_opts(Rest, [{force_stop, true}|Acc]); +transform_opts([{repeat, Repeat}|Rest], Acc) -> + transform_opts(Rest, [{repeat, + ec_cnv:to_integer(Repeat)}|Acc]); +transform_opts([{create_priv_dir, CreatePrivDir}|Rest], Acc) -> + transform_opts(Rest, [{create_priv_dir, + to_atoms(split_string(CreatePrivDir))}|Acc]); +transform_opts([{multiply_timetraps, MultiplyTimetraps}|Rest], Acc) -> + transform_opts(Rest, [{multiply_timetraps, + ec_cnv:to_integer(MultiplyTimetraps)}|Acc]); +transform_opts([{event_handler, EventHandler}|Rest], Acc) -> + transform_opts(Rest, [{event_handler, parse_term(EventHandler)}|Acc]); +transform_opts([{silent_connections, SilentConnections}|Rest], Acc) -> + transform_opts(Rest, [{silent_connections, + to_atoms(split_string(SilentConnections))}|Acc]); +transform_opts([{verbosity, "all"}|Rest], Acc) -> + transform_opts(Rest, [{verbosity, all}|Acc]); +transform_opts([{verbosity, Verbosity}|Rest], Acc) -> + transform_opts(Rest, [{verbosity, parse_term(Verbosity)}|Acc]); +transform_opts([{logopts, LogOpts}|Rest], Acc) -> + transform_opts(Rest, [{logopts, to_atoms(split_string(LogOpts))}|Acc]); +transform_opts([{userconfig, UserConfig}|Rest], Acc) -> + transform_opts(Rest, [{userconfig, parse_term(UserConfig)}|Acc]); +transform_opts([{testcase, Testcase}|Rest], Acc) -> + transform_opts(Rest, [{testcase, to_atoms(split_string(Testcase))}|Acc]); +transform_opts([{group, Group}|Rest], Acc) -> % @TODO handle "" + % Input is a list or an atom. It can also be a nested list. + transform_opts(Rest, [{group, parse_term(Group)}|Acc]); +transform_opts([{Key, Val}|Rest], Acc) when is_list(Val) -> + % Default to splitting a string on comma, that works fine for both flat + % lists of which there are many and single-items. + Val1 = case split_string(Val) of + [Val2] -> + Val2; + Val2 -> + Val2 + end, + transform_opts(Rest, [{Key, Val1}|Acc]); +transform_opts([{Key, Val}|Rest], Acc) -> + transform_opts(Rest, [{Key, Val}|Acc]). + +to_atoms(List) -> + lists:map(fun(X) -> list_to_atom(X) end, List). + +split_string(String) -> + string:tokens(String, ","). + +parse_term(String) -> + String1 = "[" ++ String ++ "].", + {ok, Tokens, _} = erl_scan:string(String1), + case erl_parse:parse_term(Tokens) of + {ok, [Terms]} -> + Terms; + Term -> + Term + end. + +create_dirs(Opts) -> + LogDir = proplists:get_value(logdir, Opts), + TestDir = proplists:get_value(dir, Opts), + ensure_logdir(LogDir), + ensure_testdir(TestDir), + ok. + +ensure_logdir(Logdir) -> + case ec_file:is_dir(Logdir) of + true -> + ok; + false -> + ec_file:mkdir_path(Logdir) + end. + +ensure_testdir(Testdir) -> + case ec_file:is_dir(Testdir) of + false -> + ?INFO("Test directory ~s does not exist:\n", + [Testdir]), + ?FAIL; + _ -> ok + end. + help(dir) -> "Test folder (default: test/)"; help(suite) -> @@ -141,40 +233,3 @@ help(ct_hooks) -> ""; help(userconfig) -> "". - -build_options(State) -> - Arguments = rebar_state:command_args(State), - Opts = parse_args(Arguments, []), - lists:keymerge(1, Opts, defaults(State)). - -defaults(State) -> - Logdir = filename:join([rebar_state:dir(State), "logs"]), - ok = ensure_logdir(Logdir), - Testdir = filename:join([rebar_state:dir(State), "test"]), - ok = ensure_testdir(Testdir), - [{dir, Testdir}, - {logdir, Logdir}]. - -parse_args([], Opts) -> - Opts; -parse_args([Pair|Rest], Opts) -> - [Key, Val] = string:tokens(Pair, "="), - Key0 = list_to_atom(Key), - parse_args(Rest, [{Key0, string:tokens(Val, " ")}|Opts]). - -ensure_logdir(Logdir) -> - case ec_file:is_dir(Logdir) of - true -> - ok; - false -> - ec_file:mkdir_path(Logdir) - end. - -ensure_testdir(Testdir) -> - case ec_file:is_dir(Testdir) of - false -> - ?INFO("Test directory ~s does not exist:\n", - [Testdir]), - ?FAIL; - _ -> ok - end. -- cgit v1.1 From b0a48436bfe710d8cc2f9f6c6d1d3c992cf0e069 Mon Sep 17 00:00:00 2001 From: omarkj Date: Wed, 26 Nov 2014 10:09:03 -0800 Subject: Return errors when tests fail. --- src/rebar_prv_common_test.erl | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 2e847a2..7313527 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -36,13 +36,20 @@ do(State) -> {Opts, _} = rebar_state:command_parsed_args(State), Opts1 = transform_opts(Opts), ok = create_dirs(Opts1), - expand_test_deps(filename:absname(rebar_state:get(State, test_deps_dir, ?DEFAULT_TEST_DEPS_DIR))), - ct:run_test(Opts1), - {ok, State}. + expand_test_deps(filename:absname(rebar_state:get(State, test_deps_dir, + ?DEFAULT_TEST_DEPS_DIR))), + case ct:run_test(Opts1) of + {_, 0, _} -> {ok, State}; + {_, FailedCount, _} -> {error, {?MODULE, {failures_running_tests, + FailedCount}}}; + {error, Reason} -> {error, {?MODULE, {error_running_tests, Reason}}} + end. -spec format_error(any()) -> iolist(). -format_error(Reason) -> - io_lib:format("~p", [Reason]). +format_error({failures_running_tests, FailedCount}) -> + io_lib:format("Failures occured running tests: ~p", [FailedCount]); +format_error({error_running_tests, Reason}) -> + io_lib:format("Error running tests: ~p", [Reason]). expand_test_deps(Dir) -> Apps = filelib:wildcard(filename:join([Dir, "*", "ebin"])), -- cgit v1.1 From a93723189f49fab1fd02c5ad1b6b1dc88be86528 Mon Sep 17 00:00:00 2001 From: omarkj Date: Wed, 26 Nov 2014 10:11:09 -0800 Subject: Correctly parse create_priv_dir. --- src/rebar_prv_common_test.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index 7313527..c61e752 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -107,7 +107,7 @@ transform_opts([{repeat, Repeat}|Rest], Acc) -> ec_cnv:to_integer(Repeat)}|Acc]); transform_opts([{create_priv_dir, CreatePrivDir}|Rest], Acc) -> transform_opts(Rest, [{create_priv_dir, - to_atoms(split_string(CreatePrivDir))}|Acc]); + to_atoms(CreatePrivDir)}|Acc]); transform_opts([{multiply_timetraps, MultiplyTimetraps}|Rest], Acc) -> transform_opts(Rest, [{multiply_timetraps, ec_cnv:to_integer(MultiplyTimetraps)}|Acc]); -- cgit v1.1 From cd2f72d2aac41720b6018c440db33f0d52297e6b Mon Sep 17 00:00:00 2001 From: omarkj Date: Wed, 26 Nov 2014 10:16:08 -0800 Subject: Transform silent_connections well and parse verbosity. Verbosity can be a integer but I am parsing it as a term. This will work for integers as well as terms. --- src/rebar_prv_common_test.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rebar_prv_common_test.erl b/src/rebar_prv_common_test.erl index c61e752..59f5565 100644 --- a/src/rebar_prv_common_test.erl +++ b/src/rebar_prv_common_test.erl @@ -113,11 +113,11 @@ transform_opts([{multiply_timetraps, MultiplyTimetraps}|Rest], Acc) -> ec_cnv:to_integer(MultiplyTimetraps)}|Acc]); transform_opts([{event_handler, EventHandler}|Rest], Acc) -> transform_opts(Rest, [{event_handler, parse_term(EventHandler)}|Acc]); +transform_opts([{silent_connections, "all"}|Rest], Acc) -> + transform_opts(Rest, [{silent_connections, all}|Acc]); transform_opts([{silent_connections, SilentConnections}|Rest], Acc) -> transform_opts(Rest, [{silent_connections, to_atoms(split_string(SilentConnections))}|Acc]); -transform_opts([{verbosity, "all"}|Rest], Acc) -> - transform_opts(Rest, [{verbosity, all}|Acc]); transform_opts([{verbosity, Verbosity}|Rest], Acc) -> transform_opts(Rest, [{verbosity, parse_term(Verbosity)}|Acc]); transform_opts([{logopts, LogOpts}|Rest], Acc) -> -- cgit v1.1