OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of unittest.matcher; | 5 part of unittest.matcher; |
6 | 6 |
7 /** | 7 /** |
8 * Returns a matcher which matches [Iterable]s in which all elements | 8 * Returns a matcher which matches [Iterable]s in which all elements |
9 * match the given [matcher]. | 9 * match the given [matcher]. |
10 */ | 10 */ |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 Description describeMismatch(item, Description mismatchDescription, | 101 Description describeMismatch(item, Description mismatchDescription, |
102 Map matchState, bool verbose) { | 102 Map matchState, bool verbose) { |
103 if (item is !Iterable) { | 103 if (item is !Iterable) { |
104 return mismatchDescription.add('is not an Iterable'); | 104 return mismatchDescription.add('is not an Iterable'); |
105 } else { | 105 } else { |
106 return _matcher.describeMismatch(item, mismatchDescription, | 106 return _matcher.describeMismatch(item, mismatchDescription, |
107 matchState, verbose); | 107 matchState, verbose); |
108 } | 108 } |
109 } | 109 } |
110 } | 110 } |
111 | |
111 /** | 112 /** |
112 * Returns a matcher which matches [Iterable]s that have the same | 113 * Returns a matcher which matches [Iterable]s that have the same |
113 * length and the same elements as [expected], but not necessarily in | 114 * length and the same elements as [expected], but not necessarily in |
114 * the same order. Note that this is O(n^2) so should only be used on | 115 * the same order. Note that this is O(n^2) so should only be used on |
115 * small objects. | 116 * small objects. |
116 */ | 117 */ |
117 Matcher unorderedEquals(Iterable expected) => | 118 Matcher unorderedEquals(Iterable expected) => |
118 new _UnorderedEquals(expected); | 119 new _UnorderedEquals(expected); |
119 | 120 |
120 class _UnorderedEquals extends Matcher { | 121 class _UnorderedEquals extends Matcher { |
121 Iterable _expected; | 122 Iterable _expected; |
122 | 123 |
123 _UnorderedEquals(Iterable this._expected); | 124 _UnorderedEquals(Iterable this._expected); |
124 | 125 |
125 String _test(item) { | 126 String _test(item) { |
126 if (item is !Iterable) { | 127 if (item is !Iterable) { |
127 return 'not iterable'; | 128 return 'not iterable'; |
128 } | 129 } |
129 // Check the lengths are the same. | 130 // Check the lengths are the same. |
130 var expectedLength = _expected.length; | 131 var expectedLength = _expected.length; |
131 var actualLength = item.length; | 132 var actualLength = item.length; |
132 if (expectedLength > actualLength) { | 133 if (expectedLength > actualLength) { |
133 return 'has too few elements (${actualLength} < ${expectedLength})'; | 134 return 'has too few elements (${actualLength} < ${expectedLength})'; |
134 } else if (expectedLength < actualLength) { | 135 } else if (expectedLength < actualLength) { |
135 return 'has too many elements (${actualLength} > ${expectedLength})'; | 136 return 'has too many elements (${actualLength} > ${expectedLength})'; |
136 } | 137 } |
137 List<bool> matched = new List<bool>(actualLength); | 138 List<bool> matched = new List<bool>(actualLength); |
Siggi Cherem (dart-lang)
2013/12/17 00:32:03
might be worth adjusting this too (use the filled
| |
138 for (var i = 0; i < actualLength; i++) { | 139 for (var i = 0; i < actualLength; i++) { |
139 matched[i] = false; | 140 matched[i] = false; |
140 } | 141 } |
141 var expectedPosition = 0; | 142 var expectedPosition = 0; |
142 for (var expectedElement in _expected) { | 143 for (var expectedElement in _expected) { |
143 var actualPosition = 0; | 144 var actualPosition = 0; |
144 var gotMatch = false; | 145 var gotMatch = false; |
145 for (var actualElement in item) { | 146 for (var actualElement in item) { |
146 if (!matched[actualPosition]) { | 147 if (!matched[actualPosition]) { |
147 if (expectedElement == actualElement) { | 148 if (expectedElement == actualElement) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
186 addDescriptionOf(item). | 187 addDescriptionOf(item). |
187 add(' not an Iterable'); | 188 add(' not an Iterable'); |
188 } else { | 189 } else { |
189 return super.describeMismatch(item, mismatchDescription, matchState, | 190 return super.describeMismatch(item, mismatchDescription, matchState, |
190 verbose); | 191 verbose); |
191 } | 192 } |
192 } | 193 } |
193 } | 194 } |
194 | 195 |
195 /** | 196 /** |
197 * Returns a matcher which matches [Iterable]s whose elements match the matchers | |
198 * in [expected], but not necessarily in the same order. | |
199 * | |
200 * Note that this is `O(n^2)` and so should only be used on small objects. | |
201 */ | |
202 Matcher unorderedMatches(Iterable expected) => | |
203 new _UnorderedMatches(expected); | |
204 | |
205 class _UnorderedMatches extends Matcher { | |
Siggi Cherem (dart-lang)
2013/12/17 00:32:03
seems like there is a lot of code in common here a
nweiz
2013/12/17 03:33:47
I intentionally avoided going too deep on modifyin
Siggi Cherem (dart-lang)
2013/12/17 18:48:45
I think it is worth the effort for the matchers li
| |
206 final List<Matcher> _expected; | |
207 | |
208 _UnorderedMatches(Iterable expected) | |
209 : _expected = expected.map(wrapMatcher).toList(); | |
210 | |
211 String _test(item) { | |
212 if (item is !Iterable) return 'not iterable'; | |
213 item = item.toList(); | |
214 | |
215 // Check the lengths are the same. | |
216 if (_expected.length > item.length) { | |
217 return 'has too few elements (${item.length} < ${_expected.length})'; | |
218 } else if (_expected.length < item.length) { | |
219 return 'has too many elements (${item.length} > ${_expected.length})'; | |
220 } | |
221 | |
222 var matched = new List<bool>.filled(item.length, false); | |
223 var expectedPosition = 0; | |
224 for (var expectedMatcher in _expected) { | |
225 var actualPosition = 0; | |
226 var gotMatch = false; | |
227 for (var actualElement in item) { | |
228 if (!matched[actualPosition]) { | |
229 if (expectedMatcher.matches(actualElement, {})) { | |
230 matched[actualPosition] = gotMatch = true; | |
231 break; | |
232 } | |
233 } | |
234 ++actualPosition; | |
235 } | |
236 | |
237 if (!gotMatch) { | |
238 return new StringDescription() | |
239 .add('has no match for ') | |
240 .addDescriptionOf(expectedMatcher) | |
241 .add(' at index ${expectedPosition}') | |
242 .toString(); | |
243 } | |
244 | |
245 ++expectedPosition; | |
246 } | |
247 return null; | |
248 } | |
249 | |
250 bool matches(item, Map mismatchState) => _test(item) == null; | |
251 | |
252 Description describe(Description description) => | |
253 description | |
254 .add('matches ') | |
255 .addAll('[', ', ', ']', _expected) | |
256 .add(' unordered'); | |
257 | |
258 Description describeMismatch(item, Description mismatchDescription, | |
259 Map matchState, bool verbose) => | |
260 mismatchDescription.add(_test(item)); | |
261 } | |
262 | |
263 /** | |
196 * A pairwise matcher for iterable. You can pass an arbitrary [comparator] | 264 * A pairwise matcher for iterable. You can pass an arbitrary [comparator] |
197 * function that takes an expected and actual argument which will be applied | 265 * function that takes an expected and actual argument which will be applied |
198 * to each pair in order. [description] should be a meaningful name for | 266 * to each pair in order. [description] should be a meaningful name for |
199 * the comparator. | 267 * the comparator. |
200 */ | 268 */ |
201 Matcher pairwiseCompare(Iterable expected, Function comparator, | 269 Matcher pairwiseCompare(Iterable expected, Function comparator, |
202 String description) => | 270 String description) => |
203 new _PairwiseCompare(expected, comparator, description); | 271 new _PairwiseCompare(expected, comparator, description); |
204 | 272 |
205 class _PairwiseCompare extends _IterableMatcher { | 273 class _PairwiseCompare extends _IterableMatcher { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 return mismatchDescription. | 308 return mismatchDescription. |
241 add('has '). | 309 add('has '). |
242 addDescriptionOf(matchState["actual"]). | 310 addDescriptionOf(matchState["actual"]). |
243 add(' which is not $_description '). | 311 add(' which is not $_description '). |
244 addDescriptionOf(matchState["expected"]). | 312 addDescriptionOf(matchState["expected"]). |
245 add(' at index ${matchState["index"]}'); | 313 add(' at index ${matchState["index"]}'); |
246 } | 314 } |
247 } | 315 } |
248 } | 316 } |
249 | 317 |
OLD | NEW |