| 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 |