kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 | // for details. All rights reserved. Use of this source code is governed by a |
| 3 | // BSD-style license that can be found in the LICENSE file. |
| 4 | |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 5 | library matcher.operator_matchers; |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 6 | |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 7 | import 'interfaces.dart'; |
kevmoo@google.com | e0d6dfd | 2014-07-31 22:50:50 +0000 | [diff] [blame] | 8 | import 'util.dart'; |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 9 | |
| 10 | /// This returns a matcher that inverts [matcher] to its logical negation. |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 11 | Matcher isNot(matcher) => new _IsNot(wrapMatcher(matcher)); |
| 12 | |
| 13 | class _IsNot extends Matcher { |
| 14 | final Matcher _matcher; |
| 15 | |
kevmoo@google.com | e0d6dfd | 2014-07-31 22:50:50 +0000 | [diff] [blame] | 16 | const _IsNot(this._matcher); |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 17 | |
| 18 | bool matches(item, Map matchState) => !_matcher.matches(item, matchState); |
| 19 | |
| 20 | Description describe(Description description) => |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 21 | description.add('not ').addDescriptionOf(_matcher); |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 22 | } |
| 23 | |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 24 | /// This returns a matcher that matches if all of the matchers passed as |
srawlins@google.com | 3bec76d | 2014-10-06 16:23:04 +0000 | [diff] [blame] | 25 | /// arguments (up to 7) match. |
| 26 | /// |
| 27 | /// Instead of passing the matchers separately they can be passed as a single |
| 28 | /// List argument. Any argument that is not a matcher is implicitly wrapped in a |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 29 | /// Matcher to check for equality. |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 30 | Matcher allOf(arg0, [arg1, arg2, arg3, arg4, arg5, arg6]) { |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 31 | return new _AllOf(_wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6)); |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 32 | } |
| 33 | |
| 34 | class _AllOf extends Matcher { |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 35 | final List<Matcher> _matchers; |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 36 | |
| 37 | const _AllOf(this._matchers); |
| 38 | |
| 39 | bool matches(item, Map matchState) { |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 40 | for (var matcher in _matchers) { |
| 41 | if (!matcher.matches(item, matchState)) { |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 42 | addStateInfo(matchState, {'matcher': matcher}); |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 43 | return false; |
| 44 | } |
| 45 | } |
| 46 | return true; |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 47 | } |
| 48 | |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 49 | Description describeMismatch( |
| 50 | item, Description mismatchDescription, Map matchState, bool verbose) { |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 51 | var matcher = matchState['matcher']; |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 52 | matcher.describeMismatch( |
| 53 | item, mismatchDescription, matchState['state'], verbose); |
kevmoo@google.com | f9c7742 | 2014-03-21 23:50:50 +0000 | [diff] [blame] | 54 | return mismatchDescription; |
| 55 | } |
| 56 | |
| 57 | Description describe(Description description) => |
| 58 | description.addAll('(', ' and ', ')', _matchers); |
| 59 | } |
| 60 | |
srawlins@google.com | 3bec76d | 2014-10-06 16:23:04 +0000 | [diff] [blame] | 61 | /// Matches if any of the given matchers evaluate to true. |
| 62 | /// |
| 63 | /// The arguments can be a set of matchers as separate parameters |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 64 | /// (up to 7), or a List of matchers. |
| 65 | /// |
| 66 | /// The matchers are evaluated from left to right using short-circuit |
| 67 | /// evaluation, so evaluation stops as soon as a matcher returns true. |
| 68 | /// |
| 69 | /// Any argument that is not a matcher is implicitly wrapped in a |
| 70 | /// Matcher to check for equality. |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 71 | Matcher anyOf(arg0, [arg1, arg2, arg3, arg4, arg5, arg6]) { |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 72 | return new _AnyOf(_wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6)); |
kevmoo@google.com | 27da56e | 2014-06-02 16:54:44 +0000 | [diff] [blame] | 73 | } |
kevmoo@google.com | 1495cd1 | 2014-06-03 07:10:01 +0000 | [diff] [blame] | 74 | |
| 75 | class _AnyOf extends Matcher { |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 76 | final List<Matcher> _matchers; |
kevmoo@google.com | 1495cd1 | 2014-06-03 07:10:01 +0000 | [diff] [blame] | 77 | |
| 78 | const _AnyOf(this._matchers); |
| 79 | |
| 80 | bool matches(item, Map matchState) { |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 81 | for (var matcher in _matchers) { |
| 82 | if (matcher.matches(item, matchState)) { |
| 83 | return true; |
| 84 | } |
| 85 | } |
| 86 | return false; |
kevmoo@google.com | 1495cd1 | 2014-06-03 07:10:01 +0000 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | Description describe(Description description) => |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 90 | description.addAll('(', ' or ', ')', _matchers); |
kevmoo@google.com | 1495cd1 | 2014-06-03 07:10:01 +0000 | [diff] [blame] | 91 | } |
| 92 | |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 93 | List<Matcher> _wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { |
kevmoo@google.com | e0d6dfd | 2014-07-31 22:50:50 +0000 | [diff] [blame] | 94 | Iterable<Matcher> matchers; |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 95 | if (arg0 is List) { |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 96 | if (arg1 != null || |
| 97 | arg2 != null || |
| 98 | arg3 != null || |
| 99 | arg4 != null || |
| 100 | arg5 != null || |
| 101 | arg6 != null) { |
kevmoo@google.com | e0d6dfd | 2014-07-31 22:50:50 +0000 | [diff] [blame] | 102 | throw new ArgumentError('If arg0 is a List, all other arguments must be' |
| 103 | ' null.'); |
| 104 | } |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 105 | |
kevmoo@google.com | e0d6dfd | 2014-07-31 22:50:50 +0000 | [diff] [blame] | 106 | matchers = arg0; |
| 107 | } else { |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 108 | matchers = |
| 109 | [arg0, arg1, arg2, arg3, arg4, arg5, arg6].where((e) => e != null); |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 110 | } |
| 111 | |
Kevin Moore | 0d23f15 | 2015-01-14 14:28:53 -0800 | [diff] [blame] | 112 | return matchers.map((e) => wrapMatcher(e)).toList(); |
kevmoo@google.com | 94a9bcf | 2014-06-05 17:11:03 +0000 | [diff] [blame] | 113 | } |