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

Side by Side Diff: pkg/unittest/lib/src/core_matchers.dart

Issue 15755005: Change output of string equality match failures. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 months 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
OLDNEW
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 matcher; 5 part of matcher;
6 6
7 /** 7 /**
8 * Returns a matcher that matches empty strings, maps or iterables 8 * Returns a matcher that matches empty strings, maps or iterables
9 * (including collections). 9 * (including collections).
10 */ 10 */
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 Description describe(Description description) => 79 Description describe(Description description) =>
80 description.add('same instance as ').addDescriptionOf(_expected); 80 description.add('same instance as ').addDescriptionOf(_expected);
81 } 81 }
82 82
83 /** 83 /**
84 * Returns a matcher that does a deep recursive match. This only works 84 * Returns a matcher that does a deep recursive match. This only works
85 * with scalars, Maps and Iterables. To handle cyclic structures a 85 * with scalars, Maps and Iterables. To handle cyclic structures a
86 * recursion depth [limit] can be provided. The default limit is 100. 86 * recursion depth [limit] can be provided. The default limit is 100.
87 */ 87 */
88 Matcher equals(expected, [limit=100]) => 88 Matcher equals(expected, [limit=100]) =>
89 new _DeepMatcher(expected, limit); 89 expected is String
90 ? new _StringEqualsMatcher(expected)
91 : new _DeepMatcher(expected, limit);
90 92
91 class _DeepMatcher extends BaseMatcher { 93 class _DeepMatcher extends BaseMatcher {
92 final _expected; 94 final _expected;
93 final int _limit; 95 final int _limit;
94 var count; 96 var count;
95 97
96 _DeepMatcher(this._expected, [limit = 1000]) : this._limit = limit; 98 _DeepMatcher(this._expected, [limit = 1000]) : this._limit = limit;
97 99
98 String _compareIterables(expected, actual, matcher, depth) { 100 String _compareIterables(expected, actual, matcher, depth) {
99 if (actual is !Iterable) { 101 if (actual is !Iterable) {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 bool matches(item, MatchState matchState) => _match(_expected, item) == null; 201 bool matches(item, MatchState matchState) => _match(_expected, item) == null;
200 202
201 Description describe(Description description) => 203 Description describe(Description description) =>
202 description.addDescriptionOf(_expected); 204 description.addDescriptionOf(_expected);
203 205
204 Description describeMismatch(item, Description mismatchDescription, 206 Description describeMismatch(item, Description mismatchDescription,
205 MatchState matchState, bool verbose) => 207 MatchState matchState, bool verbose) =>
206 mismatchDescription.add(_match(_expected, item)); 208 mismatchDescription.add(_match(_expected, item));
207 } 209 }
208 210
211 /** A special equality matcher for strings. */
212 class _StringEqualsMatcher extends BaseMatcher {
213 final String _value;
214
215 _StringEqualsMatcher(this._value);
216
217 bool get showActualValue => true;
218
219 bool matches(item, MatchState mismatchState) => _value == item;
220
221 Description describe(Description description) =>
222 description.addDescriptionOf(_value);
223
224 Description describeMismatch(item, Description mismatchDescription,
225 MatchState matchState, bool verbose) {
226 if (item is! String) {
227 return mismatchDescription.addDescriptionOf(item).add(' not a string');
228 } else {
229 var buff = new StringBuffer();
230 buff.write('Strings are not equal.');
231 var escapedItem = _escape(item);
232 var escapedValue = _escape(_value);
233 int minLength = escapedItem.length < escapedValue.length ?
234 escapedItem.length : escapedValue.length;
235 int start;
236 for (start = 0; start < minLength; start++) {
237 if (escapedValue.codeUnitAt(start) != escapedItem.codeUnitAt(start)) {
238 break;
239 }
240 }
241 if (start == minLength) {
242 if (escapedValue.length < escapedItem.length) {
243 buff.write(' Both strings start the same, but the given value also'
244 ' has the following trailing characters: ');
245 _writeTrailing(buff, escapedItem, escapedValue.length);
246 } else {
247 buff.write(' Both strings start the same, but the given value is'
248 ' missing the following trailing characters: ');
249 _writeTrailing(buff, escapedValue, escapedItem.length);
250 }
251 } else {
252 buff.write('\nExpected: ');
253 _writeLeading(buff, escapedValue, start);
254 _writeTrailing(buff, escapedValue, start);
255 buff.write('\n Actual: ');
256 _writeLeading(buff, escapedItem, start);
257 _writeTrailing(buff, escapedItem, start);
258 buff.write('\n ');
259 for (int i = (start > 10 ? 14 : start); i > 0; i--) buff.write(' ');
260 buff.write('^\n Differ at position $start');
261 }
262
263 return mismatchDescription.replace(buff.toString());
264 }
265 }
266
267 static String _escape(String s) =>
268 s.replaceAll('\n', '\\n').replaceAll('\r', '\\r').replaceAll('\t', '\\t');
269
270 static String _writeLeading(StringBuffer buff, String s, int start) {
271 if (start > 10) {
272 buff.write('... ');
273 buff.write(s.substring(start - 10, start));
274 } else {
275 buff.write(s.substring(0, start));
276 }
277 }
278
279 static String _writeTrailing(StringBuffer buff, String s, int start) {
280 if (start + 10 > s.length) {
281 buff.write(s.substring(start));
282 } else {
283 buff.write(s.substring(start, start + 10));
284 buff.write(' ...');
285 }
286 }
287 }
288
209 /** A matcher that matches any value. */ 289 /** A matcher that matches any value. */
210 const Matcher anything = const _IsAnything(); 290 const Matcher anything = const _IsAnything();
211 291
212 class _IsAnything extends BaseMatcher { 292 class _IsAnything extends BaseMatcher {
213 const _IsAnything(); 293 const _IsAnything();
214 bool matches(item, MatchState matchState) => true; 294 bool matches(item, MatchState matchState) => true;
215 Description describe(Description description) => 295 Description describe(Description description) =>
216 description.add('anything'); 296 description.add('anything');
217 } 297 }
218 298
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 description.add(_featureDescription).add(' ').addDescriptionOf(_matcher); 781 description.add(_featureDescription).add(' ').addDescriptionOf(_matcher);
702 782
703 Description describeMismatch(item, Description mismatchDescription, 783 Description describeMismatch(item, Description mismatchDescription,
704 MatchState matchState, bool verbose) { 784 MatchState matchState, bool verbose) {
705 mismatchDescription.add(_featureName).add(' '); 785 mismatchDescription.add(_featureName).add(' ');
706 _matcher.describeMismatch(matchState.state['feature'], mismatchDescription, 786 _matcher.describeMismatch(matchState.state['feature'], mismatchDescription,
707 matchState.state['innerState'], verbose); 787 matchState.state['innerState'], verbose);
708 return mismatchDescription; 788 return mismatchDescription;
709 } 789 }
710 } 790 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698