Skip to content

Commit 29e62a3

Browse files
authored
Merge pull request #24 from clojerl/12.run.tests.command
[Closes #12] Run tests command
2 parents 72d477b + 4d6df30 commit 29e62a3

File tree

7 files changed

+193
-57
lines changed

7 files changed

+193
-57
lines changed

src/rebar3_clojerl.erl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
-export([init/1]).
44

55
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
6-
init(State0) ->
7-
{ok, State1} = rebar3_clojerl_prv_compile:init(State0),
8-
{ok, State2} = rebar3_clojerl_prv_repl:init(State1),
9-
{ok, _ } = rebar3_clojerl_prv_release:init(State2).
6+
init(State) ->
7+
Commands = [ fun rebar3_clojerl_prv_compile:init/1
8+
, fun rebar3_clojerl_prv_test:init/1
9+
, fun rebar3_clojerl_prv_repl:init/1
10+
, fun rebar3_clojerl_prv_release:init/1
11+
],
12+
FoldFun = fun(F, {ok, StateAcc}) -> F(StateAcc) end,
13+
lists:foldl(FoldFun, {ok, State}, Commands).

src/rebar3_clojerl.hrl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-define(CLOJERL, <<"clojerl">>).
2+
-define(CLJINFO_FILE, <<"cljinfo">>).
3+
4+
-define(DEFAULT_SRC_DIRS, ["src"]).
5+
-define(DEFAULT_TEST_DIRS, ["test"]).

src/rebar3_clojerl_prv_compile.erl

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
-module(rebar3_clojerl_prv_compile).
22

3+
-include("rebar3_clojerl.hrl").
4+
35
-export([init/1, do/1, format_error/1]).
46

57
-define(PROVIDER, compile).
68
-define(NAMESPACE, clojerl).
79
-define(DEPS, [{default, compile}]).
8-
-define(DEFAULT_SRC_DIRS, ["src"]).
9-
10-
-define(CLOJERL, <<"clojerl">>).
11-
-define(CLJINFO_FILE, <<"cljinfo">>).
1210

1311
-type config() :: #{ ebin_dir => file:name()
1412
, protocols_dir => file:name()
@@ -38,10 +36,10 @@ init(State) ->
3836
do(State) ->
3937
DepsPaths = rebar_state:code_paths(State, all_deps),
4038
ok = code:add_pathsa(DepsPaths),
41-
ok = ensure_clojerl(State),
39+
ok = rebar3_clojerl_utils:ensure_clojerl(State),
4240

43-
AllApps = all_apps(State),
44-
Apps = lists:filter(is_not_dep_name_fun(?CLOJERL), AllApps),
41+
AllApps = rebar3_clojerl_utils:all_apps(State),
42+
Apps = rebar3_clojerl_utils:filter_app(AllApps, ?CLOJERL),
4543
Config = #{protocols_dir => protocols_dir(State)},
4644

4745
restore_duplicates(AllApps),
@@ -58,10 +56,6 @@ format_error(Reason) ->
5856
%% Internal functions
5957
%% =============================================================================
6058

61-
-spec all_apps(rebar_state:t()) -> [rebar_app_info:t()].
62-
all_apps(State) ->
63-
lists:usort(rebar_state:all_deps(State)) ++ rebar_state:project_apps(State).
64-
6559
-spec protocols_dir(rebar_state:t()) -> file:name().
6660
protocols_dir(State) ->
6761
%% Get the first application from this project.
@@ -134,32 +128,6 @@ update_app_file({Dir, Filepaths}) ->
134128
[] -> ok
135129
end.
136130

137-
-spec ensure_clojerl(rebar_state:t()) -> ok.
138-
ensure_clojerl(State) ->
139-
case find_dep(State, ?CLOJERL) of
140-
notfound ->
141-
rebar_api:abort("Clojerl was not found as a dependency", []);
142-
{ok, _} ->
143-
ok = clojerl:start()
144-
end.
145-
146-
-spec find_dep(rebar_state:t(), binary()) -> notfound | {ok, any()}.
147-
find_dep(State, Name) ->
148-
Deps = rebar_state:all_deps(State),
149-
case lists:filter(is_dep_name_fun(Name), Deps) of
150-
[] -> notfound;
151-
[DepInfo] -> {ok, DepInfo}
152-
end.
153-
154-
-spec is_dep_name_fun(binary()) -> fun((_) -> boolean()).
155-
is_dep_name_fun(Name) ->
156-
fun(Dep) -> Name =:= rebar_app_info:name(Dep) end.
157-
158-
-spec is_not_dep_name_fun(binary()) -> fun((_) -> boolean()).
159-
is_not_dep_name_fun(Name) ->
160-
IsDepName = is_dep_name_fun(Name),
161-
fun(Dep) -> not IsDepName(Dep) end.
162-
163131
-spec compile(rebar_app_info:t(), config()) -> boolean().
164132
compile(AppInfo, Config0) ->
165133
Graph = load_graph(AppInfo),
@@ -200,7 +168,9 @@ compile_clje(Src, Config) ->
200168
catch
201169
_:Reason ->
202170
Stacktrace = erlang:get_stacktrace(),
203-
rebar_api:debug("Stacktrace:~n~s", [clj_utils:stacktrace(Stacktrace)]),
171+
rebar_api:debug( "Stacktrace:~n~s"
172+
, [clj_utils:format_stacktrace(Stacktrace)]
173+
),
204174
rebar_api:abort( "Error while compiling ~s: ~s"
205175
, [Src, clj_rt:str(Reason)]
206176
)
@@ -280,7 +250,7 @@ find_files_to_compile(AppInfo, Config) ->
280250
, digraph:graph()
281251
) -> [{file:name(), file:name()}].
282252
find_files_to_compile(SrcDir, EbinDirs, ProtoDir, Graph) ->
283-
SrcFiles = rebar_utils:find_files(SrcDir, "clj[ce]"),
253+
SrcFiles = rebar_utils:find_files(SrcDir, ".clj[ce]"),
284254
[ {SrcDir, Source}
285255
|| Source <- SrcFiles,
286256
should_compile_file(Source, SrcDir, EbinDirs, ProtoDir, Graph)

src/rebar3_clojerl_prv_release.erl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
-define(NAMESPACE, clojerl).
77
-define(DEPS, [{clojerl, compile}]).
88

9-
-define(CLOJERL, <<"clojerl">>).
10-
119
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
1210
init(State) ->
1311
Provider = providers:create([ {namespace, ?NAMESPACE}

src/rebar3_clojerl_prv_repl.erl

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ repl(State) ->
5555
code:add_pathsa(DepsPaths),
5656

5757
{Opts, _} = rebar_state:command_parsed_args(State),
58-
ok = maybe_start_apps(Opts),
59-
ok = maybe_set_sname(Opts),
58+
ok = maybe_start_apps(Opts),
59+
ok = rebar3_clojerl_utils:maybe_set_sname(Opts),
6060

6161
try
6262
ok = 'clojerl.Var':push_bindings(Bindings),
@@ -74,13 +74,3 @@ maybe_start_apps(Opts) ->
7474
[application:ensure_all_started(Name) || Name <- Apps],
7575
ok
7676
end.
77-
78-
-spec maybe_set_sname(opts()) -> ok.
79-
maybe_set_sname(Opts) ->
80-
case proplists:get_value(sname, Opts, undefined) of
81-
undefined -> ok;
82-
SNameStr ->
83-
SName = list_to_atom(SNameStr),
84-
{ok, _} = net_kernel:start([SName, shortnames]),
85-
ok
86-
end.

src/rebar3_clojerl_prv_test.erl

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
-module(rebar3_clojerl_prv_test).
2+
3+
-include("rebar3_clojerl.hrl").
4+
5+
-export([init/1, do/1, format_error/1]).
6+
7+
-define(PROVIDER, test).
8+
-define(NAMESPACE, clojerl).
9+
-define(DEPS, [{clojerl, compile}]).
10+
11+
%% =============================================================================
12+
%% Public API
13+
%% =============================================================================
14+
15+
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
16+
init(State) ->
17+
Opts = [ {sname, undefined, "sname", string, "Erlang node name."}
18+
, {ns, undefined, "ns", string, "Namespace to test."}
19+
, {var, undefined, "var", string, "Var to test."}
20+
],
21+
Provider = providers:create([ {namespace, ?NAMESPACE}
22+
, {name, ?PROVIDER}
23+
, {module, ?MODULE}
24+
, {bare, true}
25+
, {deps, ?DEPS}
26+
, {example, "rebar3 clojerl test"}
27+
, {opts, Opts}
28+
, {short_desc, "Test clojerl project"}
29+
, {desc, "Test clojerl project"}
30+
]),
31+
{ok, rebar_state:add_provider(State, Provider)}.
32+
33+
-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
34+
do(State) ->
35+
{Opts, _} = rebar_state:command_parsed_args(State),
36+
ok = rebar3_clojerl_utils:maybe_set_sname(Opts),
37+
38+
DepsPaths = rebar_state:code_paths(State, all_deps),
39+
ok = code:add_pathsa(DepsPaths),
40+
ok = rebar3_clojerl_utils:ensure_clojerl(State),
41+
42+
Apps = rebar_state:project_apps(State),
43+
44+
try
45+
[test(AppInfo, Opts) || AppInfo <- Apps]
46+
catch _:Reason ->
47+
Stacktrace = erlang:get_stacktrace(),
48+
rebar_api:debug( "Stacktrace:~n~s"
49+
, [clj_utils:format_stacktrace(Stacktrace)]
50+
),
51+
rebar_api:abort( "Error while testing: ~s"
52+
, [clj_rt:str(Reason)]
53+
)
54+
end,
55+
{ok, State}.
56+
57+
-spec format_error(any()) -> iolist().
58+
format_error(Reason) ->
59+
io_lib:format("~p", [Reason]).
60+
61+
%% =============================================================================
62+
%% Internal functions
63+
%% =============================================================================
64+
65+
-spec test(rebar_app_info:t(), [{atom(), any()}]) -> ok.
66+
test(AppInfo, Opts) ->
67+
TestDirs = rebar_app_info:get(AppInfo, clje_test_dirs, ?DEFAULT_TEST_DIRS),
68+
ok = code:add_pathsa(TestDirs),
69+
NsOpt = proplists:get_value(ns, Opts, undefined),
70+
VarOpt = proplists:get_value(var, Opts, undefined),
71+
72+
NsSymbols = case NsOpt of
73+
undefined -> lists:flatmap(fun find_tests/1, TestDirs);
74+
NsOpt -> [clj_rt:symbol(list_to_binary(NsOpt))]
75+
end,
76+
77+
%% TODO: maybe change this to a compilation of the file
78+
['clojure.core':require([NsSym]) || NsSym <- NsSymbols],
79+
80+
Var = case {NsOpt, VarOpt} of
81+
{undefined, _} -> undefined;
82+
{_, undefined} -> undefined;
83+
_ ->
84+
VarSymbol = clj_rt:symbol( list_to_binary(NsOpt)
85+
, list_to_binary(VarOpt)
86+
),
87+
'clojure.core':'find-var'(VarSymbol)
88+
end,
89+
90+
rebar_api:debug("Test namespaces: ~p", [clj_rt:str(NsSymbols)]),
91+
92+
case Var of
93+
undefined -> 'clojure.test':'run-tests'(NsSymbols);
94+
_ -> 'clojure.test':'test-var'(Var)
95+
end,
96+
ok.
97+
98+
-spec find_tests(file:name()) -> ['clojerl.Symbol':type()].
99+
find_tests(TestDir) ->
100+
[path_to_symbol(X) || X <- filelib:wildcard("**/*.clj[ce]", TestDir)].
101+
102+
-spec path_to_symbol(string()) -> 'clojerl.Symbol':type().
103+
path_to_symbol(Path) ->
104+
Rootname = filename:rootname(Path),
105+
RootnameBin = list_to_binary(Rootname),
106+
NsName = clj_utils:resource_to_ns(RootnameBin),
107+
clj_rt:symbol(NsName).

src/rebar3_clojerl_utils.erl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
-module(rebar3_clojerl_utils).
2+
3+
-include("rebar3_clojerl.hrl").
4+
5+
-export([ ensure_clojerl/1
6+
, all_apps/1
7+
, find_dep/2
8+
, filter_app/2
9+
, maybe_set_sname/1
10+
]).
11+
12+
-type opts() :: [{atom(), any()}].
13+
14+
-spec ensure_clojerl(rebar_state:t()) -> ok.
15+
ensure_clojerl(State) ->
16+
case find_dep(State, ?CLOJERL) of
17+
notfound ->
18+
rebar_api:abort("Clojerl was not found as a dependency", []);
19+
{ok, _} ->
20+
ok = clojerl:start()
21+
end.
22+
23+
-spec all_apps(rebar_state:t()) -> [rebar_app_info:t()].
24+
all_apps(State) ->
25+
lists:usort(rebar_state:all_deps(State)) ++ rebar_state:project_apps(State).
26+
27+
-spec find_dep(rebar_state:t(), binary()) -> notfound | {ok, any()}.
28+
find_dep(State, Name) ->
29+
Deps = rebar_state:all_deps(State),
30+
case lists:filter(is_dep_name_fun(Name), Deps) of
31+
[] -> notfound;
32+
[DepInfo] -> {ok, DepInfo}
33+
end.
34+
35+
-spec filter_app([rebar_app_info:t()], binary()) -> notfound | {ok, any()}.
36+
filter_app(Apps, Name) ->
37+
lists:filter(is_not_dep_name_fun(Name), Apps).
38+
39+
-spec is_dep_name_fun(binary()) -> fun((_) -> boolean()).
40+
is_dep_name_fun(Name) ->
41+
fun(Dep) -> Name =:= rebar_app_info:name(Dep) end.
42+
43+
-spec is_not_dep_name_fun(binary()) -> fun((_) -> boolean()).
44+
is_not_dep_name_fun(Name) ->
45+
IsDepName = is_dep_name_fun(Name),
46+
fun(Dep) -> not IsDepName(Dep) end.
47+
48+
-spec maybe_set_sname(opts()) -> ok.
49+
maybe_set_sname(Opts) ->
50+
case proplists:get_value(sname, Opts, undefined) of
51+
undefined -> ok;
52+
SNameStr ->
53+
SName = list_to_atom(SNameStr),
54+
case net_kernel:start([SName, shortnames]) of
55+
{ok, _} -> ok;
56+
{error, Reason} ->
57+
rebar_api:warn( "Couldn't start distribution and assign name ~p: ~p"
58+
, [SName, Reason]
59+
)
60+
end,
61+
ok
62+
end.

0 commit comments

Comments
 (0)