Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: pkg/matcher/lib/src/iterable_matchers.dart

Issue 807193003: Re-apply "Remove unittest and matcher from the repo." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review changes Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/matcher/lib/src/interfaces.dart ('k') | pkg/matcher/lib/src/map_matchers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
5 library matcher.iterable_matchers;
6
7 import 'core_matchers.dart';
8 import 'description.dart';
9 import 'interfaces.dart';
10 import 'util.dart';
11
12 /// Returns a matcher which matches [Iterable]s in which all elements
13 /// match the given [matcher].
14 Matcher everyElement(matcher) => new _EveryElement(wrapMatcher(matcher));
15
16 class _EveryElement extends _IterableMatcher {
17 final Matcher _matcher;
18
19 _EveryElement(Matcher this._matcher);
20
21 bool matches(item, Map matchState) {
22 if (item is! Iterable) {
23 return false;
24 }
25 var i = 0;
26 for (var element in item) {
27 if (!_matcher.matches(element, matchState)) {
28 addStateInfo(matchState, {'index': i, 'element': element});
29 return false;
30 }
31 ++i;
32 }
33 return true;
34 }
35
36 Description describe(Description description) =>
37 description.add('every element(').addDescriptionOf(_matcher).add(')');
38
39 Description describeMismatch(item, Description mismatchDescription,
40 Map matchState, bool verbose) {
41 if (matchState['index'] != null) {
42 var index = matchState['index'];
43 var element = matchState['element'];
44 mismatchDescription.add('has value ').addDescriptionOf(element).
45 add(' which ');
46 var subDescription = new StringDescription();
47 _matcher.describeMismatch(element, subDescription, matchState['state'],
48 verbose);
49 if (subDescription.length > 0) {
50 mismatchDescription.add(subDescription.toString());
51 } else {
52 mismatchDescription.add("doesn't match ");
53 _matcher.describe(mismatchDescription);
54 }
55 mismatchDescription.add(' at index $index');
56 return mismatchDescription;
57 }
58 return super.describeMismatch(item, mismatchDescription,
59 matchState, verbose);
60 }
61 }
62
63 /// Returns a matcher which matches [Iterable]s in which at least one
64 /// element matches the given [matcher].
65 Matcher anyElement(matcher) => new _AnyElement(wrapMatcher(matcher));
66
67 class _AnyElement extends _IterableMatcher {
68 final Matcher _matcher;
69
70 _AnyElement(this._matcher);
71
72 bool matches(item, Map matchState) {
73 return item.any((e) => _matcher.matches(e, matchState));
74 }
75
76 Description describe(Description description) =>
77 description.add('some element ').addDescriptionOf(_matcher);
78 }
79
80 /// Returns a matcher which matches [Iterable]s that have the same
81 /// length and the same elements as [expected], in the same order.
82 ///
83 /// This is equivalent to [equals] but does not recurse.
84 Matcher orderedEquals(Iterable expected) => new _OrderedEquals(expected);
85
86 class _OrderedEquals extends Matcher {
87 final Iterable _expected;
88 Matcher _matcher;
89
90 _OrderedEquals(this._expected) {
91 _matcher = equals(_expected, 1);
92 }
93
94 bool matches(item, Map matchState) =>
95 (item is Iterable) && _matcher.matches(item, matchState);
96
97 Description describe(Description description) =>
98 description.add('equals ').addDescriptionOf(_expected).add(' ordered');
99
100 Description describeMismatch(item, Description mismatchDescription,
101 Map matchState, bool verbose) {
102 if (item is !Iterable) {
103 return mismatchDescription.add('is not an Iterable');
104 } else {
105 return _matcher.describeMismatch(item, mismatchDescription,
106 matchState, verbose);
107 }
108 }
109 }
110
111 /// Returns a matcher which matches [Iterable]s that have the same length and
112 /// the same elements as [expected], but not necessarily in the same order.
113 ///
114 /// Note that this is O(n^2) so should only be used on small objects.
115 Matcher unorderedEquals(Iterable expected) => new _UnorderedEquals(expected);
116
117 class _UnorderedEquals extends _UnorderedMatches {
118 final List _expectedValues;
119
120 _UnorderedEquals(Iterable expected)
121 : super(expected.map(equals)),
122 _expectedValues = expected.toList();
123
124 Description describe(Description description) =>
125 description
126 .add('equals ')
127 .addDescriptionOf(_expectedValues)
128 .add(' unordered');
129 }
130
131 /// Iterable matchers match against [Iterable]s. We add this intermediate
132 /// class to give better mismatch error messages than the base Matcher class.
133 abstract class _IterableMatcher extends Matcher {
134 const _IterableMatcher();
135 Description describeMismatch(item, Description mismatchDescription,
136 Map matchState, bool verbose) {
137 if (item is! Iterable) {
138 return mismatchDescription.
139 addDescriptionOf(item).
140 add(' not an Iterable');
141 } else {
142 return super.describeMismatch(item, mismatchDescription, matchState,
143 verbose);
144 }
145 }
146 }
147
148 /// Returns a matcher which matches [Iterable]s whose elements match the
149 /// matchers in [expected], but not necessarily in the same order.
150 ///
151 /// Note that this is `O(n^2)` and so should only be used on small objects.
152 Matcher unorderedMatches(Iterable expected) => new _UnorderedMatches(expected);
153
154 class _UnorderedMatches extends Matcher {
155 final List<Matcher> _expected;
156
157 _UnorderedMatches(Iterable expected)
158 : _expected = expected.map(wrapMatcher).toList();
159
160 String _test(item) {
161 if (item is! Iterable) return 'not iterable';
162 item = item.toList();
163
164 // Check the lengths are the same.
165 if (_expected.length > item.length) {
166 return 'has too few elements (${item.length} < ${_expected.length})';
167 } else if (_expected.length < item.length) {
168 return 'has too many elements (${item.length} > ${_expected.length})';
169 }
170
171 var matched = new List<bool>.filled(item.length, false);
172 var expectedPosition = 0;
173 for (var expectedMatcher in _expected) {
174 var actualPosition = 0;
175 var gotMatch = false;
176 for (var actualElement in item) {
177 if (!matched[actualPosition]) {
178 if (expectedMatcher.matches(actualElement, {})) {
179 matched[actualPosition] = gotMatch = true;
180 break;
181 }
182 }
183 ++actualPosition;
184 }
185
186 if (!gotMatch) {
187 return new StringDescription()
188 .add('has no match for ')
189 .addDescriptionOf(expectedMatcher)
190 .add(' at index ${expectedPosition}')
191 .toString();
192 }
193
194 ++expectedPosition;
195 }
196 return null;
197 }
198
199 bool matches(item, Map mismatchState) => _test(item) == null;
200
201 Description describe(Description description) =>
202 description
203 .add('matches ')
204 .addAll('[', ', ', ']', _expected)
205 .add(' unordered');
206
207 Description describeMismatch(item, Description mismatchDescription,
208 Map matchState, bool verbose) =>
209 mismatchDescription.add(_test(item));
210 }
211
212 /// A pairwise matcher for [Iterable]s.
213 ///
214 /// The [comparator] function, taking an expected and an actual argument, and
215 /// returning whether they match, will be applied to each pair in order.
216 /// [description] should be a meaningful name for the comparator.
217 Matcher pairwiseCompare(Iterable expected, bool comparator(a, b),
218 String description) =>
219 new _PairwiseCompare(expected, comparator, description);
220
221 typedef bool _Comparator(a, b);
222
223 class _PairwiseCompare extends _IterableMatcher {
224 final Iterable _expected;
225 final _Comparator _comparator;
226 final String _description;
227
228 _PairwiseCompare(this._expected, this._comparator, this._description);
229
230 bool matches(item, Map matchState) {
231 if (item is! Iterable) return false;
232 if (item.length != _expected.length) return false;
233 var iterator = item.iterator;
234 var i = 0;
235 for (var e in _expected) {
236 iterator.moveNext();
237 if (!_comparator(e, iterator.current)) {
238 addStateInfo(matchState, {'index': i, 'expected': e,
239 'actual': iterator.current});
240 return false;
241 }
242 i++;
243 }
244 return true;
245 }
246
247 Description describe(Description description) =>
248 description.add('pairwise $_description ').addDescriptionOf(_expected);
249
250 Description describeMismatch(item, Description mismatchDescription,
251 Map matchState, bool verbose) {
252 if (item is !Iterable) {
253 return mismatchDescription.add('is not an Iterable');
254 } else if (item.length != _expected.length) {
255 return mismatchDescription.
256 add('has length ${item.length} instead of ${_expected.length}');
257 } else {
258 return mismatchDescription.
259 add('has ').
260 addDescriptionOf(matchState["actual"]).
261 add(' which is not $_description ').
262 addDescriptionOf(matchState["expected"]).
263 add(' at index ${matchState["index"]}');
264 }
265 }
266 }
OLDNEW
« no previous file with comments | « pkg/matcher/lib/src/interfaces.dart ('k') | pkg/matcher/lib/src/map_matchers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698