From 349c6917eba481d5691dcd167c2d19c5e6488455 Mon Sep 17 00:00:00 2001 From: Ted Burghart Date: Mon, 16 Jan 2017 15:26:13 -0500 Subject: [PATCH] Rebar3 is in, Rebar2 is out. - Replaces how hamcrest.hrl is generated, see comments in priv/build/scripts/generate_include.escript - Moved .app to src, where Rebar3 will always find it. - Rewrote some specs to make dialyzer happy. - Made hamcrest:matchspec non-opaque, because that just doesn't work with a shared record definition. - Adds Thumbs support. At present, tests require QuviQ Erlang QuickCheck, and will be skipped (returning success) if it's not installed. This commit removes support for PropEr due to its license. Refer to: https://github.com/basho/erlang_protobuffs/pull/19 https://github.com/manopapad/proper/issues/29 It _may_ be worth supporting Triq at some point: https://github.com/krestenkrab/triq --- .erlang | 1 - .gitignore | 61 ++++--- .thumbs.yml | 25 +++ ebin/hamcrest.app | 8 - hamcrest-erlang.epm | 1 - priv/build/plugins/eqc_resolver.erl | 61 ------- priv/build/plugins/header_generator.erl | 65 -------- priv/build/scripts/bootstrap-deps.sh | 7 - priv/build/scripts/generate_include.escript | 167 ++++++++++++++++++++ priv/build/templates/hamcrest.hrl.src | 1 - rebar.config | 162 ++++++++++++++++--- src/hamcrest.app.src | 8 + src/hamcrest.erl | 2 +- src/hamcrest_matchers.erl | 21 ++- test/hamcrest_SUITE.erl | 30 ++-- test/hamcrest_matchers_SUITE.erl | 18 ++- 16 files changed, 419 insertions(+), 219 deletions(-) delete mode 100644 .erlang create mode 100644 .thumbs.yml delete mode 100644 ebin/hamcrest.app delete mode 100644 hamcrest-erlang.epm delete mode 100644 priv/build/plugins/eqc_resolver.erl delete mode 100644 priv/build/plugins/header_generator.erl delete mode 100644 priv/build/scripts/bootstrap-deps.sh create mode 100755 priv/build/scripts/generate_include.escript create mode 100644 src/hamcrest.app.src diff --git a/.erlang b/.erlang deleted file mode 100644 index 480440e..0000000 --- a/.erlang +++ /dev/null @@ -1 +0,0 @@ -{ok, PWD} = file:get_cwd(), code:add_patha(filename:join(PWD, "deps/proper-1.0/ebin")). diff --git a/.gitignore b/.gitignore index d6882d0..2836d03 100755 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,38 @@ -*.kpf -*.pyc +# rebar +*.crashdump +/.cache/ +/.eqc* +/.eunit/ +/.rebar/ +/.rebar3/ +/_build/ +/_checkouts +/deps +/rebar.lock + +# work environments +*.bak +*.dump +*.iml +*.plt +*.sublime-project +*.sublime-workspace +*.tmp +*.txt +*_plt +*~ +.DS_Store +.idea/ +.project +.settings/ +.tm_properties +erln8.config +tmp/ + +# Erlang build/test artifacts +*.app *.beam -*.o -*.so -*.swp -.rebar/ -build/* -^build$ -Emakefile -coverage -coverage/* -erl_crash.dump -test/logs/ -ebin/*.beam -logs/* -include/hamcrest.hrl -qc.hrl -deps/ -ct_*/ -all_runs.html -ct_* -jquery-latest.js -jquery.tablesorter.min.js -variables-ct@localhost +/include/hamcrest.hrl +/doc/ +/ebin/ +log/ diff --git a/.thumbs.yml b/.thumbs.yml new file mode 100644 index 0000000..e99be85 --- /dev/null +++ b/.thumbs.yml @@ -0,0 +1,25 @@ +minimum_reviewers: 2 +merge: true +merge_method: merge +build_steps: + # clean relevant profiles to ensure they succeed + - rebar3 clean --all + - rebar3 as prod clean --all + - rebar3 as check clean --all + - rebar3 as test clean --all + - rebar3 as validate clean --all + # compile relevant profiles to ensure they succeed + # - rebar3 as validate compile + - rebar3 compile + - rebar3 as prod compile + - rebar3 as check compile + - rebar3 as test compile + # these are the real tests + - rebar3 as check brt-deps --check + - rebar3 as check xref + - rebar3 as check dialyzer + - rebar3 ct + # last, but not least, do the docs build? + - rebar3 edoc +org_mode: true +timeout: 1800 diff --git a/ebin/hamcrest.app b/ebin/hamcrest.app deleted file mode 100644 index fc18da9..0000000 --- a/ebin/hamcrest.app +++ /dev/null @@ -1,8 +0,0 @@ -{application, - hamcrest, - [{description,"Hamcrest Matcher Library"}, - {vsn,"0.3.0-basho"}, - {modules,[hamcrest,hamcrest_matchers,hamcrest_term]}, - {registered,[]}, - {applications,[kernel,stdlib]}, - {env,[]}]}. diff --git a/hamcrest-erlang.epm b/hamcrest-erlang.epm deleted file mode 100644 index 284edbe..0000000 --- a/hamcrest-erlang.epm +++ /dev/null @@ -1 +0,0 @@ -[{deps, [{"manopapad/proper", []}]}]. diff --git a/priv/build/plugins/eqc_resolver.erl b/priv/build/plugins/eqc_resolver.erl deleted file mode 100644 index 94adab9..0000000 --- a/priv/build/plugins/eqc_resolver.erl +++ /dev/null @@ -1,61 +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. -%% ----------------------------------------------------------------------------- -%% @author Tim Watson -%% @copyright 2010 Tim Watson. -%% -%% Generates hamcrest.hrl header file during build process. Loaded by rebar. -%% ----------------------------------------------------------------------------- --module(eqc_resolver). - --export([preprocess/2]). - -preprocess(Config, _) -> - case rebar_utils:processing_base_dir(Config) of - false -> {ok, []}; - true -> case code:lib_dir(eqc, include) of - {error, bad_name} -> - write_include("proper"), - {ok, []}; - _ -> - write_include("eqc"), - Deps = rebar_config:get_local(Config, deps, []), - DepsNoPropEr = proplists:delete(proper, Deps), - Config2 = rebar_config:set(Config, deps, DepsNoPropEr), - {ok, Config2, []} - end - end. - -write_include(Lib) -> - file:write_file(filename:join(test_dir(), "qc.hrl"), - include(Lib)). - -test_dir() -> - filename:join(rebar_utils:get_cwd(), "test"). - -include(Lib) -> - [<<"-include_lib(\"">>, - Lib, <<"/include/">>, - Lib, <<".hrl\").\n">>, - <<"-define(">>, Lib, <<", true).">>]. diff --git a/priv/build/plugins/header_generator.erl b/priv/build/plugins/header_generator.erl deleted file mode 100644 index b5cb255..0000000 --- a/priv/build/plugins/header_generator.erl +++ /dev/null @@ -1,65 +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. -%% ----------------------------------------------------------------------------- -%% @author Tim Watson -%% @copyright 2010 Tim Watson. -%% -%% Generates hamcrest.hrl header file during build process. Loaded by rebar. -%% ----------------------------------------------------------------------------- --module(header_generator). --export([post_compile/2]). - -post_compile(_, AppFile) -> - case lists:suffix("hamcrest.app", AppFile) of - true -> - code:add_patha(filename:join(rebar_utils:get_cwd(), "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)), - ImportList = string:substr(Expr, 1, length(Expr) - 2), - 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}])), - ResBin = erlang:iolist_to_binary(Res), - Dest = filename:absname(filename:join(["include", "hamcrest.hrl"])), - case file:read_file(Dest) of - {ok, ResBin} -> - rebar_log:log(info, "Header file(s) untouched.~n", []), - ok; - _ -> - case file:write_file(Dest, ResBin) of - ok -> - rebar_log:log(info, "Header file(s) generated.~n", []), - ok; - {error, WriteError} -> - rebar_utils:abort("Failed to write ~p: ~p~n", [Dest, WriteError]) - end - end; - false -> - ok - end. diff --git a/priv/build/scripts/bootstrap-deps.sh b/priv/build/scripts/bootstrap-deps.sh deleted file mode 100644 index 8454a1e..0000000 --- a/priv/build/scripts/bootstrap-deps.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/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 \ No newline at end of file diff --git a/priv/build/scripts/generate_include.escript b/priv/build/scripts/generate_include.escript new file mode 100755 index 0000000..5654ba8 --- /dev/null +++ b/priv/build/scripts/generate_include.escript @@ -0,0 +1,167 @@ +#!/usr/bin/env escript +%% -*- mode: erlang; erlang-indent-level: 4; indent-tabs-mode: nil -*- +%% ------------------------------------------------------------------- +%% +%% Copyright (c) 2017 Basho Technologies, Inc. +%% +%% This file is provided to you under the Apache License, +%% Version 2.0 (the "License"); you may not use this file +%% except in compliance with the License. You may obtain +%% a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, +%% software distributed under the License is distributed on an +%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%% KIND, either express or implied. See the License for the +%% specific language governing permissions and limitations +%% under the License. +%% +%% ------------------------------------------------------------------- +% +% Based (very loosely) on priv/build/plugins/header_generator.erl from the +% upstream original. That one was a Rebar2 plugin, and made assumptions about +% the current directory and relative paths that all go out the window with +% Rebar3. +% +% This is a standalone escript, suitable for invocation as a post-compile shell +% hook in Rebar3. As such it doesn't have access to Rebar's functions, so it +% doesn't use mustache templating, and determines file paths from the location +% of the script and source beam at runtime. +% + +% +% In Rebar3, LibDirs should be: +% [ +% /_checkouts/hamcrest +% /_build//lib/hamcrest +% ] +% We'll use the first one that exists. +% +main(LibDirs) -> + log(debug, "LibDirs = ~p~n", [LibDirs]), + + BeamSub = filename:join("ebin", "hamcrest_matchers.beam"), + HInSub = filename:join(["priv", "build", "templates", "hamcrest.hrl.src"]), + HOutSub = filename:join("include", "hamcrest.hrl"), + Require = [BeamSub, HInSub], + + LibDir = case find_lib_dir(LibDirs, Require) of + false -> + log(error, + "Hamcrest directory not found, or required files missing: ~p~n", + [Require]), + erlang:halt(1); + Dir -> + log(debug, "LibDir = ~p~n", [Dir]), + Dir + end, + Beam = filename:join(LibDir, BeamSub), + HeadIn = filename:join(LibDir, HInSub), + HeadOut = filename:join(LibDir, HOutSub), + + Update = case filelib:last_modified(HeadOut) of + 0 -> + true; + HOutDT -> + HOutTS = calendar:datetime_to_gregorian_seconds(HOutDT), + + HOutTS < calendar:datetime_to_gregorian_seconds(filelib:last_modified(Beam)) + orelse + HOutTS < calendar:datetime_to_gregorian_seconds(filelib:last_modified(HeadIn)) + end, + RC = if + Update -> + catch do_update(HeadOut, Beam, HeadIn); + true -> + log(info, "~s is up to date.~n", [filename:basename(HeadOut)]), + 0 + end, + erlang:halt(RC). + +do_update(HeadOut, Beam, HeadIn) -> + BeamMod = case filelib:ensure_dir(HeadOut) of + ok -> + case code:load_abs(filename:rootname(Beam)) of + {module, Mod} -> + Mod; + {error, LoadErr} -> + log(error, "~s: ~p~n", [Beam, LoadErr]), + erlang:throw(1) + end; + {error, DirErr} -> + log(error, "~s: ~p~n", [HeadOut, file:format_error(DirErr)]), + erlang:throw(1) + end, + Exports = lists:filter( + fun({module_info, _}) -> + false; + (_) -> + true + end, BeamMod:module_info(exports)), + Imports = [io_lib:format("~s/~b", [F, A]) || {F, A} <- lists:sort(Exports)], + + case file:read_file(HeadIn) of + {ok, HSrcBin} -> + HOutData = io_lib:format("~s-import(~s, [~n ~s~n]).~n", + [HSrcBin, BeamMod, string:join(Imports, ",\n ")]), + log(info, "Updating ~s~n", [filename:basename(HeadOut)]), + case file:write_file(HeadOut, HOutData) of + ok -> + 0; + {error, WErr} -> + log(error, "~s: ~p~n", [HeadOut, file:format_error(WErr)]), + 1 + end; + {error, RErr} -> + log(error, "~s: ~p~n", [HeadIn, file:format_error(RErr)]), + 1 + end. + +find_lib_dir([LibDir | LibDirs], Required) -> + case check_lib_files(Required, LibDir) of + true -> + LibDir; + _ -> + find_lib_dir(LibDirs, Required) + end; +find_lib_dir([], _) -> + false. + +check_lib_files([File | Files], LibDir) -> + case filelib:is_regular(filename:join(LibDir, File)) of + true -> + check_lib_files(Files, LibDir); + _ -> + false + end; +check_lib_files([], _) -> + true. + +% +% Try to look kind of like Rebar3, but I'm not bothering with colors. +% +log(error, Fmt, Args) -> + io:format(standard_error, "===> Error: " ++ Fmt, Args); +log(warn, Fmt, Args) -> + case os:getenv("QUIET") of + false -> + io:format(standard_error, "===> Warning: " ++ Fmt, Args); + _ -> + ok + end; +log(info, Fmt, Args) -> + case os:getenv("QUIET") of + false -> + io:format("===> " ++ Fmt, Args); + _ -> + ok + end; +log(debug, Fmt, Args) -> + case os:getenv("DEBUG") of + false -> + ok; + _ -> + io:format("===> " ++ Fmt, Args) + end. diff --git a/priv/build/templates/hamcrest.hrl.src b/priv/build/templates/hamcrest.hrl.src index 2ed54ca..fef678b 100644 --- a/priv/build/templates/hamcrest.hrl.src +++ b/priv/build/templates/hamcrest.hrl.src @@ -75,4 +75,3 @@ end). -endif. -import(hamcrest, [assert_that/2, assert_that/3, match/2, match/3]). --import(hamcrest_matchers, [{{ imports }}]). diff --git a/rebar.config b/rebar.config index adeb36c..ea9e65b 100644 --- a/rebar.config +++ b/rebar.config @@ -1,26 +1,138 @@ +%% -*- mode: erlang; erlang-indent-level: 4; indent-tabs-mode: nil -*- +%% ------------------------------------------------------------------- +%% +%% Copyright (c) 2017 Basho Technologies, Inc. +%% +%% This file is provided to you under the Apache License, +%% Version 2.0 (the "License"); you may not use this file +%% except in compliance with the License. You may obtain +%% a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, +%% software distributed under the License is distributed on an +%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%% KIND, either express or implied. See the License for the +%% specific language governing permissions and limitations +%% under the License. +%% +%% ------------------------------------------------------------------- +% +% This is a complete replacement of the upstream rebar.config - DO NOT MERGE! +% + +{brt_protect, true}. + +{erl_opts, [ + {platform_define, "^[0-9]+", namespaced_types}, + + warn_bif_clash, + warn_export_all, + warn_export_vars, + warn_obsolete_guard, + warn_unused_import +]}. + +{post_hooks, [ + {compile, + "priv/build/scripts/generate_include.escript" + " $REBAR_CHECKOUTS_DIR/hamcrest" + " $REBAR_DEPS_DIR/hamcrest"} +]}. + +{profiles, [ + {check, [ + {dialyzer, [ + {warnings, [ + error_handling, + no_match, + no_return, + race_conditions, + unknown, + unmatched_returns + ]} + ]}, + {erl_opts, [ + debug_info, + warnings_as_errors, + {d, 'BASHO_CHECK'} + ]}, + {xref_checks, [ + deprecated_function_calls, + deprecated_functions, + locals_not_used, + undefined_function_calls, + undefined_functions + ]} + ]}, + {docs, [ + {edoc_opts, [ + {app_default, "http://www.erlang.org/doc/man"}, + {preprocess, true}, + {macros, [ + {'EDOC', true}, + {'BASHO_DOCS', true} + ]} + ]} + ]}, + {prod, [ + {erl_opts, [ + warnings_as_errors, + {d, 'BASHO_PROD'} + ]} + ]}, + {test, [ + {cover_enabled, true}, + {erl_opts, [ + % this is a hack until it's in the BRT plugin + {d, 'EQC'}, + % and this one will go away before long ... + {platform_define, "^R", 'HAMCREST_TEST_OLD_OTP'}, + + debug_info, + nowarn_deprecated_function, + nowarn_export_all, + nowarn_unused_function, + nowarn_unused_import, + warnings_as_errors, + {d, 'BASHO_TEST'} + ]}, + {eunit_opts, [ + verbose + ]} + ]}, + {validate, [ + {erl_opts, [ + strong_validation, + no_auto_import, + warn_bif_clash, + warn_deprecated_function, + warn_deprecated_type, + warn_export_all, + warn_export_vars, + warn_missing_spec, + warn_missing_spec_all, + warn_obsolete_guard, + warn_shadow_vars, + warn_untyped_record, + warn_unused_function, + warn_unused_import, + warn_unused_record, + warn_unused_vars, + {d, 'BASHO_VALIDATE'} + ]} + ]} +]}. + +{brt_upstream, [ + {upstream, {git, "https://github.com/hyperthunk/hamcrest-erlang.git"}}, + {mirror, upstream, master} +]}. + +{plugins, [ + {basho_rebar_tools, + {git, "https://github.com/basho/basho_rebar_tools.git", + {branch, "master"} }} +]}. -{lib_dirs, ["deps"]}. -{erl_opts, [debug_info, fail_on_warning, {platform_define, "^[0-9]+", namespaced_types}]}. -{clean_files, ["logs", "build", "include/hamcrest.hrl"]}. - -{plugin_dir, "priv/build/plugins"}. -{plugins, [header_generator, eqc_resolver]}. - -{xref_checks, []}. -{xref_queries, - [{"((XC - UC) || (XU - X - B))",[]}, %% calls to undefined functions - {"(L - LU)", []}, %% local unused - {"(LU * (X - XU))", [ %% exported functions only used locally - {hamcrest,assert_that,2}, %% NB: we're a library so this is expected... - {hamcrest,assert_that,3}, - {hamcrest,check,2}, - {hamcrest,describe,2}, - {hamcrest,heckle,2}, - {hamcrest,match,3}, - {hamcrest_matchers,check_member,2}, %% called via apply/3 - {hamcrest_matchers,equal_to,1}, - {hamcrest_matchers,foreach,1}, - {hamcrest_matchers,is_not,1}, - {hamcrest_matchers,match_mfa,3}, - {hamcrest_matchers,reverse_match_mfa,3}]}, - {"(DF * (XU + LU))", []}]}. diff --git a/src/hamcrest.app.src b/src/hamcrest.app.src new file mode 100644 index 0000000..b13f6ba --- /dev/null +++ b/src/hamcrest.app.src @@ -0,0 +1,8 @@ +{application, hamcrest, [ + {description, "Hamcrest Matcher Library"}, + {vsn, "git"}, + {modules, []}, + {registered, []}, + {applications, [kernel, stdlib]}, + {env, []} +]}. diff --git a/src/hamcrest.erl b/src/hamcrest.erl index cf1d329..b31d131 100644 --- a/src/hamcrest.erl +++ b/src/hamcrest.erl @@ -48,7 +48,7 @@ %%% Types %%%============================================================================ --opaque matchspec() :: #'hamcrest.matchspec'{}. +-type matchspec() :: #'hamcrest.matchspec'{}. %%%============================================================================ %%% API diff --git a/src/hamcrest_matchers.erl b/src/hamcrest_matchers.erl index 41a9c8b..d236d96 100644 --- a/src/hamcrest_matchers.erl +++ b/src/hamcrest_matchers.erl @@ -34,8 +34,6 @@ -include("hamcrest_internal.hrl"). --import(hamcrest, [message/4]). - -export([ all_of/1, anything/0, @@ -118,6 +116,7 @@ foreach(M) when is_record(M, 'hamcrest.matchspec') -> ?MATCHER(fun(L) -> drop_matches(M, L) == [] end, M, {foreach, M#'hamcrest.matchspec'.desc}). +-spec drop_matches(hamcrest:matchspec(), list()) -> boolean() | list(). drop_matches(Match, []) -> case hamcrest:match([], Match) of true -> []; @@ -126,8 +125,8 @@ drop_matches(Match, []) -> drop_matches(Match, L) -> lists:dropwhile(fun(E) -> hamcrest:match(E, Match) end, L). --spec(any_of(list(matchfun(term()))) -> hamcrest:matchspec(); - (list(hamcrest:matchspec())) -> hamcrest:matchspec()). +-spec any_of([matchfun(term())] | [hamcrest:matchspec()]) + -> hamcrest:matchspec(). any_of(Matchers) when is_list(Matchers) -> MatchFun = fun(M) when is_function(M) -> M; @@ -142,8 +141,8 @@ any_of(Matchers) when is_list(Matchers) -> %% TODO: older syntax for type specifications - we need to support %% >= R13B for the most part... --spec all_of(list(matchfun(term()))) -> hamcrest:matchspec(); - (list(hamcrest:matchspec())) -> hamcrest:matchspec(). +-spec all_of([matchfun(term())] | [hamcrest:matchspec()]) + -> hamcrest:matchspec(). all_of(Matchers) when is_list(Matchers) -> MatchFun = fun(M) when is_function(M) -> M; (#'hamcrest.matchspec'{matcher=F}) -> F @@ -171,9 +170,8 @@ exactly_equal_to(X) -> expected = X }. --spec(is(matchfun(term())) -> hamcrest:matchspec(); - (hamcrest:matchspec()) -> hamcrest:matchspec(); - (any()) -> hamcrest:matchspec()). +-spec is(matchfun(term()) | hamcrest:matchspec() | any()) + -> hamcrest:matchspec(). is(Matcher) when is_record(Matcher, 'hamcrest.matchspec') -> Matcher; is(Term) -> @@ -187,9 +185,8 @@ is_true() -> is_false() -> is_not(equal_to(true)). --spec(is_not(matchfun(term())) -> hamcrest:matchspec(); - (hamcrest:matchspec()) -> hamcrest:matchspec(); - (term()) -> hamcrest:matchspec()). +-spec is_not(matchfun(term()) | hamcrest:matchspec() | term()) + -> hamcrest:matchspec(). is_not(#'hamcrest.matchspec'{ matcher=MatchFun }=MatchSpec) when is_record(MatchSpec, 'hamcrest.matchspec') -> MatchSpec#'hamcrest.matchspec'{ matcher = (fun(X) -> not(MatchFun(X)) end) }; diff --git a/test/hamcrest_SUITE.erl b/test/hamcrest_SUITE.erl index d8fdd11..07dbdf5 100644 --- a/test/hamcrest_SUITE.erl +++ b/test/hamcrest_SUITE.erl @@ -30,12 +30,25 @@ %% module annotations -module(hamcrest_SUITE). +-compile(export_all). + +-ifdef(EQC). +-ifdef(HAMCREST_TEST_OLD_OTP). +-define(SKIP_TEST_REASON, otp_release_too_old). +-endif. % HAMCREST_TEST_OLD_OTP +-else. % not EQC +-define(SKIP_TEST_REASON, no_eqc). +-endif. % EQC + +-ifdef(SKIP_TEST_REASON). + +all() -> {skip, ?SKIP_TEST_REASON}. + +-else. +-include_lib("eqc/include/eqc.hrl"). -include_lib("common_test/include/ct.hrl"). --include("test.hrl"). --include("qc.hrl"). -include("../include/hamcrest.hrl"). - --compile(export_all). +-include("test.hrl"). all() -> ?CT_REGISTER_TESTS(?MODULE). @@ -107,8 +120,7 @@ is_matcher(_) -> end), ?EQC(P). --ifdef('eqc'). -something() -> eqc_gen:oneof([int(), nat(), list(char), binary()]). --else. -something() -> any(). --endif. +something() -> + eqc_gen:oneof([int(), nat(), list(char), binary()]). + +-endif. % EQC diff --git a/test/hamcrest_matchers_SUITE.erl b/test/hamcrest_matchers_SUITE.erl index 6726425..47b0466 100644 --- a/test/hamcrest_matchers_SUITE.erl +++ b/test/hamcrest_matchers_SUITE.erl @@ -29,12 +29,20 @@ %% module annotations -module(hamcrest_matchers_SUITE). --include_lib("common_test/include/ct.hrl"). --include("qc.hrl"). --include("../include/hamcrest.hrl"). - -compile(export_all). +-ifndef(EQC). +-define(SKIP_TEST_REASON, no_eqc). +-endif. % EQC + +-ifdef(SKIP_TEST_REASON). + +all() -> {skip, ?SKIP_TEST_REASON}. + +-else. +-include_lib("eqc/include/eqc.hrl"). +-include_lib("common_test/include/ct.hrl"). +-include("../include/hamcrest.hrl"). -include("test.hrl"). all() -> @@ -346,3 +354,5 @@ is_empty_pukes_for_other_inputs(_) -> fun() -> ?assertThat(10, isempty()) end, will_fail() ). + +-endif. % EQC