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 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 } | 108 } |
109 } | 109 } |
110 } | 110 } |
111 | 111 |
112 /** | 112 /** |
113 * Returns a matcher which matches [Iterable]s that have the same | 113 * Returns a matcher which matches [Iterable]s that have the same |
114 * length and the same elements as [expected], but not necessarily in | 114 * length and the same elements as [expected], but not necessarily in |
115 * 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 |
116 * small objects. | 116 * small objects. |
117 */ | 117 */ |
118 Matcher unorderedEquals(Iterable expected) => | 118 Matcher unorderedEquals(Iterable expected) => new _UnorderedEquals(expected); |
119 new _UnorderedEquals(expected); | |
120 | 119 |
121 class _UnorderedEquals extends Matcher { | 120 class _UnorderedEquals extends _UnorderedMatches { |
122 Iterable _expected; | 121 final List _expectedValues; |
123 | 122 |
124 _UnorderedEquals(Iterable this._expected); | 123 _UnorderedEquals(Iterable expected) |
125 | 124 : super(expected.map(equals)), |
126 String _test(item) { | 125 _expectedValues = expected.toList(); |
127 if (item is !Iterable) { | |
128 return 'not iterable'; | |
129 } | |
130 // Check the lengths are the same. | |
131 var expectedLength = _expected.length; | |
132 var actualLength = item.length; | |
133 if (expectedLength > actualLength) { | |
134 return 'has too few elements (${actualLength} < ${expectedLength})'; | |
135 } else if (expectedLength < actualLength) { | |
136 return 'has too many elements (${actualLength} > ${expectedLength})'; | |
137 } | |
138 List<bool> matched = new List<bool>(actualLength); | |
139 for (var i = 0; i < actualLength; i++) { | |
140 matched[i] = false; | |
141 } | |
142 var expectedPosition = 0; | |
143 for (var expectedElement in _expected) { | |
144 var actualPosition = 0; | |
145 var gotMatch = false; | |
146 for (var actualElement in item) { | |
147 if (!matched[actualPosition]) { | |
148 if (expectedElement == actualElement) { | |
149 matched[actualPosition] = gotMatch = true; | |
150 break; | |
151 } | |
152 } | |
153 ++actualPosition; | |
154 } | |
155 if (!gotMatch) { | |
156 Description reason = new StringDescription(); | |
157 reason.add('has no match for element '). | |
158 addDescriptionOf(expectedElement). | |
159 add(' at index ${expectedPosition}'); | |
160 return reason.toString(); | |
161 } | |
162 ++expectedPosition; | |
163 } | |
164 return null; | |
165 } | |
166 | |
167 bool matches(item, Map mismatchState) => (_test(item) == null); | |
168 | 126 |
169 Description describe(Description description) => | 127 Description describe(Description description) => |
170 description.add('equals ').addDescriptionOf(_expected).add(' unordered'); | 128 description |
171 | 129 .add('equals ') |
172 Description describeMismatch(item, Description mismatchDescription, | 130 .addDescriptionOf(_expectedValues) |
173 Map matchState, bool verbose) => | 131 .add(' unordered'); |
174 mismatchDescription.add(_test(item)); | |
175 } | 132 } |
176 | 133 |
177 /** | 134 /** |
178 * Iterable matchers match against [Iterable]s. We add this intermediate | 135 * Iterable matchers match against [Iterable]s. We add this intermediate |
179 * class to give better mismatch error messages than the base Matcher class. | 136 * class to give better mismatch error messages than the base Matcher class. |
180 */ | 137 */ |
181 abstract class _IterableMatcher extends Matcher { | 138 abstract class _IterableMatcher extends Matcher { |
182 const _IterableMatcher(); | 139 const _IterableMatcher(); |
183 Description describeMismatch(item, Description mismatchDescription, | 140 Description describeMismatch(item, Description mismatchDescription, |
184 Map matchState, bool verbose) { | 141 Map matchState, bool verbose) { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 return mismatchDescription. | 265 return mismatchDescription. |
309 add('has '). | 266 add('has '). |
310 addDescriptionOf(matchState["actual"]). | 267 addDescriptionOf(matchState["actual"]). |
311 add(' which is not $_description '). | 268 add(' which is not $_description '). |
312 addDescriptionOf(matchState["expected"]). | 269 addDescriptionOf(matchState["expected"]). |
313 add(' at index ${matchState["index"]}'); | 270 add(' at index ${matchState["index"]}'); |
314 } | 271 } |
315 } | 272 } |
316 } | 273 } |
317 | 274 |
OLD | NEW |