| %%%============================================================================ |
| %%% Licensed 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. |
| %%%============================================================================ |
| |
| %%% @private |
| %%% @doc This module introduces Matcher abstraction. It is an entity that can |
| %%% be created from a predicate function or a matcher provided by a supported |
| %%% framework (at the moment only Hamcrest is supported). Then it can be used |
| %%% to check that an arbitrary value meets the matcher's criteria, matches in |
| %%% other words. |
| -module(meck_matcher). |
| |
| -export_type([matcher/0]). |
| |
| %% API |
| -export([new/1]). |
| -export([is_matcher/1]). |
| -export([match_ignore/2]). |
| |
| %%%============================================================================ |
| %%% Definitions |
| %%%============================================================================ |
| |
| -record('$meck.matcher', {type :: predicate | hamcrest, |
| impl :: predicate() | hamcrest:matchspec()}). |
| |
| %%%============================================================================ |
| %%% Types |
| %%%============================================================================ |
| |
| -type predicate() :: fun((X::any()) -> any()). |
| -type matcher() :: #'$meck.matcher'{}. |
| |
| %%%============================================================================ |
| %%% API |
| %%%============================================================================ |
| |
| -spec new(predicate() | hamcrest:matchspec()) -> matcher(). |
| new(Predicate) when is_function(Predicate) -> |
| {arity, 1} = erlang:fun_info(Predicate, arity), |
| #'$meck.matcher'{type = predicate, impl = Predicate}; |
| new(Something) -> |
| case is_hamcrest_matcher(Something) of |
| true -> |
| #'$meck.matcher'{type = hamcrest, impl = Something}; |
| _Else -> |
| erlang:error({invalid_matcher, Something}) |
| end. |
| |
| -spec is_matcher(any()) -> boolean(). |
| is_matcher(#'$meck.matcher'{}) -> true; |
| is_matcher(_Other) -> false. |
| |
| %% @doc If `Something' is a {@link meck_matcher()} instance then `Value' is |
| %% matched with it, otherwise `true' is returned effectively ignoring |
| %% `Something''s value. |
| -spec match_ignore(Value::any(), Something::any()) -> boolean(). |
| match_ignore(Value, #'$meck.matcher'{type = predicate, impl = Predicate}) -> |
| Predicate(Value) == true; |
| match_ignore(Value, #'$meck.matcher'{type = hamcrest, impl = HamcrestMatcher}) -> |
| (catch hamcrest:assert_that(Value, HamcrestMatcher)) == true; |
| match_ignore(_Value, _NotMatcher) -> |
| true. |
| |
| %%%============================================================================ |
| %%% Internal functions |
| %%%============================================================================ |
| |
| -spec is_hamcrest_matcher(any()) -> boolean(). |
| is_hamcrest_matcher(Something) -> |
| try hamcrest:is_matcher(Something) |
| catch _Class:_Reason -> false |
| end. |