Chromium Code Reviews| Index: lib/unittest/core_matchers.dart |
| =================================================================== |
| --- lib/unittest/core_matchers.dart (revision 9956) |
| +++ lib/unittest/core_matchers.dart (working copy) |
| @@ -10,7 +10,7 @@ |
| class _Empty extends BaseMatcher { |
| const _Empty(); |
| - bool matches(item) { |
| + bool matches(item, MatchState matchState) { |
| if (item is Map || item is Collection) { |
| return item.isEmpty(); |
| } else if (item is String) { |
| @@ -31,14 +31,14 @@ |
| class _IsNull extends BaseMatcher { |
| const _IsNull(); |
| - bool matches(item) => item == null; |
| + bool matches(item, MatchState matchState) => item == null; |
| Description describe(Description description) => |
| description.add('null'); |
| } |
| class _IsNotNull extends BaseMatcher { |
| const _IsNotNull(); |
| - bool matches(item) => item != null; |
| + bool matches(item, MatchState matchState) => item != null; |
| Description describe(Description description) => |
| description.add('not null'); |
| } |
| @@ -51,14 +51,14 @@ |
| class _IsTrue extends BaseMatcher { |
| const _IsTrue(); |
| - bool matches(item) => item == true; |
| + bool matches(item, MatchState matchState) => item == true; |
| Description describe(Description description) => |
| description.add('true'); |
| } |
| class _IsFalse extends BaseMatcher { |
| const _IsFalse(); |
| - bool matches(item) => item != true; |
| + bool matches(item, MatchState matchState) => item != true; |
| Description describe(Description description) => |
| description.add('false'); |
| } |
| @@ -72,7 +72,7 @@ |
| class _IsSameAs extends BaseMatcher { |
| final _expected; |
| const _IsSameAs(this._expected); |
| - bool matches(item) => item === _expected; |
| + bool matches(item, MatchState matchState) => item === _expected; |
| // If all types were hashable we could show a hash here. |
| Description describe(Description description) => |
| description.add('same instance as ').addDescriptionOf(_expected); |
| @@ -177,12 +177,15 @@ |
| return reason == null ? null : reason.toString(); |
| } |
| - bool matches(item) => _match(_expected, item) == null; |
| + // TODO(gram) - see if we can make use of matchState here to avoid |
| + // recursing again in describeMismatch. |
| + bool matches(item, MatchState matchState) => _match(_expected, item) == null; |
| Description describe(Description description) => |
| description.addDescriptionOf(_expected); |
| - Description describeMismatch(item, Description mismatchDescription) => |
| + Description describeMismatch(item, Description mismatchDescription, |
| + MatchState matchState, bool verbose) => |
| mismatchDescription.add(_match(_expected, item)); |
| } |
| @@ -191,7 +194,7 @@ |
| class _IsAnything extends BaseMatcher { |
| const _IsAnything(); |
| - bool matches(item) => true; |
| + bool matches(item, MatchState matchState) => true; |
| Description describe(Description description) => |
| description.add('anything'); |
| } |
| @@ -216,7 +219,7 @@ |
| class isInstanceOf<T> extends BaseMatcher { |
| final String _name; |
| const isInstanceOf([name = 'specified type']) : this._name = name; |
| - bool matches(obj) => obj is T; |
| + bool matches(obj, MatchState matchState) => obj is T; |
| // The description here is lame :-( |
| Description describe(Description description) => |
| description.add('an instance of ${_name}'); |
| @@ -269,9 +272,10 @@ |
| class _Throws extends BaseMatcher { |
| final Matcher _matcher; |
| - const _Throws([Matcher matcher = null]) : this._matcher = matcher; |
| + const _Throws([Matcher matcher]) : |
| + this._matcher = matcher; |
| - bool matches(item) { |
| + bool matches(item, MatchState matchState) { |
| if (item is Future) { |
| // Queue up an asynchronous expectation that validates when the future |
| // completes. |
| @@ -297,8 +301,18 @@ |
| try { |
| item(); |
| return false; |
| - } catch (final e) { |
| - return _matcher == null || _matcher.matches(e); |
| + } catch (final e, final s) { |
| + if (_matcher == null) { |
| + return true; |
| + } else if (_matcher.matches(e, matchState)) { |
|
Siggi Cherem (dart-lang)
2012/07/31 17:16:40
seems you can keep it as
if (_matcher == null || _
gram
2012/07/31 17:56:01
Done.
|
| + return true; |
| + } else { |
| + matchState.state = { |
| + 'exception' :e, |
| + 'stack': s |
| + }; |
| + return false; |
| + } |
| } |
| } |
| @@ -311,26 +325,36 @@ |
| } |
| } |
| - Description describeMismatch(item, Description mismatchDescription) { |
| - if (_matcher == null) { |
| + Description describeMismatch(item, Description mismatchDescription, |
| + MatchState matchState, |
| + bool verbose) { |
| + if (_matcher == null || matchState.state == null) { |
| return mismatchDescription.add(' no exception'); |
| } else { |
| - return mismatchDescription. |
| - add(' no exception or exception does not match '). |
| - addDescriptionOf(_matcher); |
| + mismatchDescription. |
| + add(' exception ').addDescriptionOf(matchState.state['exception']); |
| + if (verbose) { |
| + mismatchDescription.add(' at '). |
| + add(matchState.state['stack'].toString()); |
| + } |
| + mismatchDescription.add(' does not match ').addDescriptionOf(_matcher); |
| + return mismatchDescription; |
| } |
| } |
| } |
| class _ReturnsNormally extends BaseMatcher { |
| - |
| const _ReturnsNormally(); |
| - bool matches(f) { |
| + bool matches(f, MatchState matchState) { |
| try { |
| f(); |
| return true; |
| - } catch (final e) { |
| + } catch (final e, final s) { |
| + matchState.state = { |
| + 'exception' : e, |
| + 'stack': s |
| + }; |
| return false; |
| } |
| } |
| @@ -338,8 +362,16 @@ |
| Description describe(Description description) => |
| description.add("return normally"); |
| - Description describeMismatch(item, Description mismatchDescription) { |
| - return mismatchDescription.add(' threw exception'); |
| + Description describeMismatch(item, Description mismatchDescription, |
| + MatchState matchState, |
| + bool verbose) { |
| + mismatchDescription.add(' threw '). |
| + addDescriptionOf(matchState.state['exception']); |
| + if (verbose) { |
| + mismatchDescription.add(' at '). |
| + add(matchState.state['stack'].toString()); |
| + } |
| + return mismatchDescription; |
| } |
| } |
| @@ -380,7 +412,7 @@ |
| class _BadNumberFormatException extends _ExceptionMatcher { |
| const _BadNumberFormatException() : super("BadNumberFormatException"); |
| - bool matches(item) => item is BadNumberFormatException; |
| + bool matches(item, MatchState matchState) => item is BadNumberFormatException; |
| } |
| /** A matcher for Exceptions. */ |
| @@ -391,7 +423,7 @@ |
| class _Exception extends _ExceptionMatcher { |
| const _Exception() : super("Exception"); |
| - bool matches(item) => item is Exception; |
| + bool matches(item, MatchState matchState) => item is Exception; |
| } |
| /** A matcher for IllegalArgumentExceptions. */ |
| @@ -403,7 +435,7 @@ |
| class _IllegalArgumentException extends _ExceptionMatcher { |
| const _IllegalArgumentException() : super("IllegalArgumentException"); |
| - bool matches(item) => item is IllegalArgumentException; |
| + bool matches(item, MatchState matchState) => item is IllegalArgumentException; |
| } |
| /** A matcher for IllegalJSRegExpExceptions. */ |
| @@ -415,7 +447,7 @@ |
| class _IllegalJSRegExpException extends _ExceptionMatcher { |
| const _IllegalJSRegExpException() : super("IllegalJSRegExpException"); |
| - bool matches(item) => item is IllegalJSRegExpException; |
| + bool matches(item, MatchState matchState) => item is IllegalJSRegExpException; |
| } |
| /** A matcher for IndexOutOfRangeExceptions. */ |
| @@ -427,7 +459,7 @@ |
| class _IndexOutOfRangeException extends _ExceptionMatcher { |
| const _IndexOutOfRangeException() : super("IndexOutOfRangeException"); |
| - bool matches(item) => item is IndexOutOfRangeException; |
| + bool matches(item, MatchState matchState) => item is IndexOutOfRangeException; |
| } |
| /** A matcher for NoSuchMethodExceptions. */ |
| @@ -439,7 +471,7 @@ |
| class _NoSuchMethodException extends _ExceptionMatcher { |
| const _NoSuchMethodException() : super("NoSuchMethodException"); |
| - bool matches(item) => item is NoSuchMethodException; |
| + bool matches(item, MatchState matchState) => item is NoSuchMethodException; |
| } |
| /** A matcher for NotImplementedExceptions. */ |
| @@ -451,7 +483,7 @@ |
| class _NotImplementedException extends _ExceptionMatcher { |
| const _NotImplementedException() : super("NotImplementedException"); |
| - bool matches(item) => item is NotImplementedException; |
| + bool matches(item, MatchState matchState) => item is NotImplementedException; |
| } |
| /** A matcher for NullPointerExceptions. */ |
| @@ -463,7 +495,7 @@ |
| class _NullPointerException extends _ExceptionMatcher { |
| const _NullPointerException() : super("NullPointerException"); |
| - bool matches(item) => item is NullPointerException; |
| + bool matches(item, MatchState matchState) => item is NullPointerException; |
| } |
| /** A matcher for UnsupportedOperationExceptions. */ |
| @@ -476,7 +508,7 @@ |
| class _UnsupportedOperationException extends _ExceptionMatcher { |
| const _UnsupportedOperationException() : |
| super("UnsupportedOperationException"); |
| - bool matches(item) => item is UnsupportedOperationException; |
| + bool matches(item, MatchState matchState) => item is UnsupportedOperationException; |
| } |
| /** |
| @@ -490,16 +522,17 @@ |
| final Matcher _matcher; |
| const _HasLength([Matcher matcher = null]) : this._matcher = matcher; |
| - bool matches(item) { |
| - return _matcher.matches(item.length); |
| + bool matches(item, MatchState matchState) { |
| + return _matcher.matches(item.length, matchState); |
| } |
| Description describe(Description description) => |
| description.add('an object with length of '). |
| addDescriptionOf(_matcher); |
| - Description describeMismatch(item, Description mismatchDescription) { |
| - super.describeMismatch(item, mismatchDescription); |
| + Description describeMismatch(item, Description mismatchDescription, |
| + MatchState matchState, bool verbose) { |
| + super.describeMismatch(item, mismatchDescription, matchState, verbose); |
| try { |
| // We want to generate a different description if there is no length |
| // property. This is harmless code that will throw if no length property |
| @@ -529,12 +562,12 @@ |
| const _Contains(this._expected); |
| - bool matches(item) { |
| + bool matches(item, MatchState matchState) { |
| if (item is String) { |
| return item.indexOf(_expected) >= 0; |
| } else if (item is Collection) { |
| if (_expected is Matcher) { |
| - return item.some((e) => _expected.matches(e)); |
| + return item.some((e) => _expected.matches(e, matchState)); |
| } else { |
| return item.some((e) => e == _expected); |
| } |
| @@ -560,7 +593,7 @@ |
| const _In(this._expected); |
| - bool matches(item) { |
| + bool matches(item, MatchState matchState) { |
| if (_expected is String) { |
| return _expected.indexOf(item) >= 0; |
| } else if (_expected is Collection) { |
| @@ -589,7 +622,7 @@ |
| const _Predicate(this._matcher, this._description); |
| - bool matches(item) => _matcher(item); |
| + bool matches(item, MatchState matchState) => _matcher(item); |
| Description describe(Description description) => |
| description.add(_description); |