Permalink
Browse files

Rebar-ize build, remove erlydtl dependency

  • Loading branch information...
1 parent f34cd0f commit 43a1e0f50d042aeadd844b00ee09d0d0cfa52863 @hyperthunk committed Jul 8, 2011
View
@@ -1,73 +0,0 @@
-# -----------------------------------------------------------------------------
-#
-# Hamcrest Erlang.
-#
-# Copyright (c) 2010 Tim Watson (watson.timothy@gmail.com)
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-# -----------------------------------------------------------------------------
-
-ERL ?= `which erl`
-ERL_LIBS := $(shell echo "./deps:`echo $$ERL_LIBS`")
-VERBOSE ?= ""
-HERE := $(shell pwd)
-BUILD := $(HERE)/build
-ERTS_VSN := $(shell escript scripts/checkvsn "5.7.5")
-ifeq ($(ERTS_VSN), 0)
- INCL_TYPES = "-b"
-endif
-INCL_TYPES ?= "NOTYPES=1"
-all: info clean compile
-
-info:
- $(info erl program located at $(ERL))
- $(info ERL_LIBS set to $(ERL_LIBS))
-
-deps: build
- mkdir -p $@
-
-build:
- mkdir -p $@
-
-deps/proper: deps
- @(env ERL_LIBS=$(ERL_LIBS) escript scripts/checkdeps "proper" | \
- env HOME=$(BUILD) ./epm install manopapad/proper \
- --build-command "make $(INCL_TYPES) && rm src/proper.app.src" \
- --config-set build_dir $(BUILD) \
- --config-set install_dir $(HERE)/deps $$VERBOSE)
-
-check: deps/proper
- @(env ERL_LIBS=$(ERL_LIBS) ./rebar $$VERBOSE get-deps check-deps)
-
-compile: check
- @(env ERL_LIBS=$(ERL_LIBS) ./rebar $$VERBOSE compile skip_deps=true)
- escript hrlgen
-
-clean:
- @(echo `env ERL_LIBS=$(ERL_LIBS) escript scripts/checkdeps "proper"` | \
- env HOME=$(BUILD) ./epm remove proper \
- --config-set build_dir $(BUILD) \
- --config-set install_dir $(HERE)/deps $$VERBOSE)
- @(./rebar $$VERBOSE clean)
-
-edoc:
- @$(ERL) -noshell -run edoc_run application '$(APP)' '"."' '[{preprocess, true},{includes, ["."]}]'
-
-test: compile
- @(env ERL_LIBS=$(ERL_LIBS) ./rebar $$VERBOSE ct skip_deps=true)
View
@@ -19,28 +19,30 @@ to pass when minor, unrelated changes to the behaviour are made.
Building Hamcrest-Erlang
------------------------
-Make sure erlydtl is on your path, or install using epm. You need to do this first until I sort out the build.
+Hamcrest-Erlang is built using rebar. You should use the bundled version of the
+rebar executable however, because the build relies on some currently unsupported
+and experimental features. The following command will compile the sources and
+generate the main header file:
- epm install erlydtl
-
-Now you can compile and test by issuing `make clean test` on the command line.
+ $ ./rebar clean compile
My first Hamcrest test
------------------------
We'll start be writing a very simple EUnit test, but instead of using EUnit's ?assertEqual macro, we use
Hamcrest's assert_that construct and the standard set of matchers:
- -module(demo1_tests).
- -compile(export_all).
-
- -import(hamcrest, [assert_that/2]).
+```erlang
+-module(demo1_tests).
+-compile(export_all).
- -include_lib("hamcrest/include/hamcrest.hrl").
+-import(hamcrest, [assert_that/2]).
- using_assert_that_test() ->
- assert_that(10, is(greater_than(2))). %% returns true
+-include_lib("hamcrest/include/hamcrest.hrl").
+using_assert_that_test() ->
+ assert_that(10, is(greater_than(2))). %% returns true
+```
The assert_that function is a stylised sentence for making a test assertion. In this example, the subject of the
assertion is the number 10 that is the first method parameter. The second method parameter is a matcher
@@ -96,51 +98,57 @@ own matcher you'll eliminate code duplication and make your tests more readable!
Let's write our own matcher for testing if a string is comprised of only digits. This is the test we want to write:
- string_is_only_digits_test() ->
- assert_that("12345", is(only_digits())).
+```erlang
+string_is_only_digits_test() ->
+ assert_that("12345", is(only_digits())).
+```
And here's the implementation:
- -module(custom_matchers).
+```erlang
+-module(custom_matchers).
- -export([only_digits/0]).
+-export([only_digits/0]).
- only_digits() ->
- fun only_digits/1.
+only_digits() ->
+ fun only_digits/1.
- only_digits(X) ->
- case re:run(X, "^[\\d]*$") of
- {match,_} -> true;
- _ -> false
- end.
+only_digits(X) ->
+ case re:run(X, "^[\\d]*$") of
+ {match,_} -> true;
+ _ -> false
+ end.
+```
The zero arity factory function we exported is responsible for creating the matcher fun, which should take 1 argument
and return the atom 'true' if it succeeds, otherwise 'false'. Although returning a fun is a simple enough way to define
a matcher, there is a another way that allows you to specify the expected versus actual input, the matcher fun and a
textual description that will be evaluated by hamcrest:assert_that/2 in case of match failures. Here's the only_digits/0
example rewritten using the alternative API:
- -module(custom_matchers).
-
- -export([only_digits/0]).
-
- only_digits() ->
- matches_regex("^[\\d]*$").
-
- matches_regex(Rx) ->
- #'hamcrest.matchspec'{
- matcher =
- fun(X) ->
- case re:run(X, Rx) of
- {match,_} -> true;
- _ -> false
- end
- end,
- desc = fun(Expected,Actual) ->
- message(string, "matching the regex", Expected, Actual)
- end,
- expected = Rx
- }.
+```erlang
+-module(custom_matchers).
+
+-export([only_digits/0]).
+
+only_digits() ->
+ matches_regex("^[\\d]*$").
+
+matches_regex(Rx) ->
+ #'hamcrest.matchspec'{
+ matcher =
+ fun(X) ->
+ case re:run(X, Rx) of
+ {match,_} -> true;
+ _ -> false
+ end
+ end,
+ desc = fun(Expected,Actual) ->
+ message(string, "matching the regex", Expected, Actual)
+ end,
+ expected = Rx
+ }.
+```
First of all, note that we're now calling the generic matches_regex/1 function which will operate over any supplied regex
compatible with the 're' module. This function is returning an instance of the 'hamcrest.matchspec' record, defined in
@@ -154,26 +162,30 @@ something like `expected a <TYPE> <DESC> <EXPECTED>, but was <ACTUAL>` when call
If you find the record syntax a little too verbose for your liking, there is a macro defined which cuts down on the noise somewhat:
- will_fail() ->
- Matcher =
- fun(F) ->
- try F() of
- _ -> false
- catch _:_ -> true
- end
- end,
- ?MATCHER(Matcher, expected_fail, {oneof, {exit,error,exception}}).
+```erlang
+will_fail() ->
+ Matcher =
+ fun(F) ->
+ try F() of
+ _ -> false
+ catch _:_ -> true
+ end
+ end,
+ ?MATCHER(Matcher, expected_fail, {oneof, {exit,error,exception}}).
+```
Another way to construct custom matchers is to use the match_mfa/3 function, which takes a module, function and its initial
arguments and matches if adding the match input to the argument list and calling `apply(M,F,A)` evaluates to true. This takes
away the headache of having to write the matchspec yourself, at the expense of a slightly less specific description provided
by assert_that if the match fails. Here's an example usage taken from the tests and another taken from the core API itself:
- isalive() ->
- match_mfa(erlang, is_process_alive, []).
+```erlang
+isalive() ->
+ match_mfa(erlang, is_process_alive, []).
- some_test(_) ->
- IsMemberOf = fun(L) ->
- match_mfa(lists, member, [L])
- end,
- assert_that(hd(X), IsMemberOf(X))
+some_test(_) ->
+ IsMemberOf = fun(L) ->
+ match_mfa(lists, member, [L])
+ end,
+ assert_that(hd(X), IsMemberOf(X))
+```
View
BIN epm
Binary file not shown.
View
@@ -1 +1 @@
-[{deps, [{"erlydtl", []}]}].
+[{deps, [{"manopapad/proper", []}]}].
@@ -1,5 +1,3 @@
-#!/usr/bin/env escript
-
%% -----------------------------------------------------------------------------
%%
%% Hamcrest Erlang.
@@ -29,27 +27,29 @@
%%
%% Generates hamcrest.hrl header file during build process.
%% -----------------------------------------------------------------------------
+-module(header_generator).
+-export([post_compile/2]).
-main(_) ->
+post_compile(_, _) ->
+ %% TODO: reconsider this munging of the code path
code:add_patha("ebin"),
- code:add_path("deps/erlydtl/ebin"),
- %% io:format("CODE:WHICH = ~p~n", [code:which(erlydtl)]),
- %% erlang:display(os:getenv("ERL_LIBS")),
- Exports = lists:filter(
- fun({F,_}) -> F /= module_info end,
- hamcrest_matchers:module_info(exports)),
+ code:add_path("deps/erlydtl/ebin"),
+ Exports = [ F || F <- hamcrest_matchers:module_info(exports),
+ F /= module_info ],
+ rebar_log:log(debug, "Adding header exports/imports: ~p~n", [Exports]),
Imports = [ io_lib:format("~s/~p", [F,A]) || {F, A} <- Exports ],
- Expr = lists:flatten(
- lists:foldl(fun(In, Acc) -> lists:concat([In, ", ", Acc]) end, "", Imports)),
+ Expr = lists:flatten(lists:foldl(
+ fun(In, Acc) -> lists:concat([In, ", ", Acc]) end, "", Imports)),
ImportList = string:substr(Expr, 1, length(Expr) - 2),
- {ok, PWD} = file:get_cwd(),
- HdrTemplate = filename:join(PWD, "priv/build/templates/hamcrest.hrl.src"),
- ok = erlydtl:compile(HdrTemplate, header_template),
- {ok, Res} = header_template:render([{imports, ImportList}]),
+ PWD = rebar_utils:get_cwd(),
+ Path = filename:join(PWD, "priv/build/templates/hamcrest.hrl.src"),
+ {ok, Bin} = file:read_file(Path),
+ Res = rebar_templater:render(Bin, dict:from_list([{imports, ImportList}])),
Dest = filename:absname(filename:join(["include", "hamcrest.hrl"])),
case file:write_file(Dest, list_to_binary(Res)) of
- ok -> io:format("Header file(s) generated.~n", []);
+ ok ->
+ rebar_log:log(info, "Header file(s) generated.~n", []),
+ ok;
{error, WriteError} ->
- io:format("Failed to write ~p: ~p~n", [Dest, WriteError]),
- halt(1)
+ rebar_utils:abort("Failed to write ~p: ~p~n", [Dest, WriteError])
end.
@@ -0,0 +1,7 @@
+#!/usr/bin/env sh
+
+export PROPER_INSTALL_PATH=`epm info proper | awk '/install dir: .*/ { print $NF }'`
+if [ "$PROPER_INSTALL_PATH" != "" ]; then
+ mkdir -p deps
+ ln -fs "$PROPER_INSTALL_PATH" deps/proper
+fi
@@ -35,30 +35,30 @@
-ifndef(assertThat).
-define(assertThat(Value, MatchSpec),
((fun () ->
- case (hamcrest:assert_that(Value, MatchSpec)) of
- true -> true;
- __V -> .erlang:error({assertion_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expected, true},
- {value, case __V of false -> __V;
- _ -> {not_a_boolean,__V}
- end}]})
- end
- end)())).
+ case (hamcrest:assert_that(Value, MatchSpec)) of
+ true -> true;
+ __V -> .erlang:error({assertion_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expected, true},
+ {value, case __V of false -> __V;
+ _ -> {not_a_boolean,__V}
+ end}]})
+ end
+ end)())).
-define(assertThat(Value, MatchSpec, After),
((fun () ->
- case (hamcrest:assert_that(Value, MatchSpec, After)) of
- true -> true;
- __V -> .erlang:error({assertion_failed,
- [{module, ?MODULE},
- {line, ?LINE},
- {expected, true},
- {value, case __V of false -> __V;
- _ -> {not_a_boolean,__V}
- end}]})
- end
- end)())).
+ case (hamcrest:assert_that(Value, MatchSpec, After)) of
+ true -> true;
+ __V -> .erlang:error({assertion_failed,
+ [{module, ?MODULE},
+ {line, ?LINE},
+ {expected, true},
+ {value, case __V of false -> __V;
+ _ -> {not_a_boolean,__V}
+ end}]})
+ end
+ end)())).
-endif.
-import(hamcrest, [assert_that/2, assert_that/3]).
View
Binary file not shown.
View
@@ -1,8 +1,15 @@
+
{lib_dirs, ["deps"]}.
{erl_opts, [debug_info, fail_on_warning]}.
{cover_enabled, true}.
-{clean_files, ["logs", "deps", "build", "include/hamcrest.hrl"]}.
+{clean_files, ["logs", "build", "include/hamcrest.hrl"]}.
{deps, [
- {proper, ".*", {git, "http://github.com/manopapad/proper.git", "master"}},
- {erlydtl, ".*", {git, "https://github.com/evanmiller/erlydtl.git", "master"}}
+ {proper, ".*", {git, "http://github.com/manopapad/proper.git", "master"}}
]}.
+
+{pre_hooks, [
+ {compile, "sh priv/build/scripts/bootstrap-deps.sh"}
+]}.
+
+{plugin_dir, "priv/build/plugins"}.
+{rebar_plugins, [header_generator]}.
Oops, something went wrong.

0 comments on commit 43a1e0f

Please sign in to comment.