LCOV - code coverage report
Current view: top level - test-0.12.24+8/lib/src/frontend - expect.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 16 49 32.7 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
       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.
       4             : 
       5             : import 'dart:async';
       6             : 
       7             : import 'package:matcher/matcher.dart';
       8             : 
       9             : import '../backend/closed_exception.dart';
      10             : import '../backend/invoker.dart';
      11             : import '../utils.dart';
      12             : import 'async_matcher.dart';
      13             : 
      14             : /// A future that emits `null`.
      15             : ///
      16             : /// We cache and re-use this value to avoid adding a new microtask hit for each
      17             : /// call to `expect()`.
      18             : final _emptyFuture = new Future.value();
      19             : 
      20             : /// An exception thrown when a test assertion fails.
      21             : class TestFailure {
      22             :   final String message;
      23             : 
      24           0 :   TestFailure(this.message);
      25             : 
      26           0 :   String toString() => message;
      27             : }
      28             : 
      29             : /// The type used for functions that can be used to build up error reports
      30             : /// upon failures in [expect].
      31             : @Deprecated("Will be removed in 0.13.0.")
      32             : typedef String ErrorFormatter(
      33             :     actual, Matcher matcher, String reason, Map matchState, bool verbose);
      34             : 
      35             : /// Assert that [actual] matches [matcher].
      36             : ///
      37             : /// This is the main assertion function. [reason] is optional and is typically
      38             : /// not supplied, as a reason is generated from [matcher]; if [reason]
      39             : /// is included it is appended to the reason generated by the matcher.
      40             : ///
      41             : /// [matcher] can be a value in which case it will be wrapped in an
      42             : /// [equals] matcher.
      43             : ///
      44             : /// If the assertion fails a [TestFailure] is thrown.
      45             : ///
      46             : /// If [skip] is a String or `true`, the assertion is skipped. The arguments are
      47             : /// still evaluated, but [actual] is not verified to match [matcher]. If
      48             : /// [actual] is a [Future], the test won't complete until the future emits a
      49             : /// value.
      50             : ///
      51             : /// If [skip] is a string, it should explain why the assertion is skipped; this
      52             : /// reason will be printed when running the test.
      53             : ///
      54             : /// In some cases extra diagnostic info can be produced on failure (for
      55             : /// example, stack traces on mismatched exceptions). To enable these,
      56             : /// [verbose] should be specified as `true`.
      57             : ///
      58             : /// Certain matchers, like [completion] and [throwsA], either match or fail
      59             : /// asynchronously. When you use [expect] with these matchers, it ensures that
      60             : /// the test doesn't complete until the matcher has either matched or failed. If
      61             : /// you want to wait for the matcher to complete before continuing the test, you
      62             : /// can call [expectLater] instead and `await` the result.
      63             : void expect(actual, matcher,
      64             :     {String reason,
      65             :     skip,
      66             :     @Deprecated("Will be removed in 0.13.0.") bool verbose: false,
      67             :     @Deprecated("Will be removed in 0.13.0.") ErrorFormatter formatter}) {
      68           5 :   _expect(actual, matcher,
      69             :       reason: reason, skip: skip, verbose: verbose, formatter: formatter);
      70             : }
      71             : 
      72             : /// Just like [expect], but returns a [Future] that completes when the matcher
      73             : /// has finished matching.
      74             : ///
      75             : /// For the [completes] and [completion] matchers, as well as [throwsA] and
      76             : /// related matchers when they're matched against a [Future], the returned
      77             : /// future completes when the matched future completes. For the [prints]
      78             : /// matcher, it completes when the future returned by the callback completes.
      79             : /// Otherwise, it completes immediately.
      80             : ///
      81             : /// If the matcher fails asynchronously, that failure is piped to the returned
      82             : /// future where it can be handled by user code.
      83             : Future expectLater(actual, matcher, {String reason, skip}) =>
      84           0 :     _expect(actual, matcher, reason: reason, skip: skip);
      85             : 
      86             : /// The implementation of [expect] and [expectLater].
      87             : Future _expect(actual, matcher,
      88             :     {String reason, skip, bool verbose: false, ErrorFormatter formatter}) {
      89             :   formatter ??= (actual, matcher, reason, matchState, verbose) {
      90           0 :     var mismatchDescription = new StringDescription();
      91           0 :     matcher.describeMismatch(actual, mismatchDescription, matchState, verbose);
      92             : 
      93           0 :     return formatFailure(matcher, actual, mismatchDescription.toString(),
      94             :         reason: reason);
      95             :   };
      96             : 
      97           5 :   if (Invoker.current == null) {
      98           0 :     throw new StateError("expect() may only be called within a test.");
      99             :   }
     100             : 
     101          10 :   if (Invoker.current.closed) throw new ClosedException();
     102             : 
     103           0 :   if (skip != null && skip is! bool && skip is! String) {
     104           0 :     throw new ArgumentError.value(skip, "skip", "must be a bool or a String");
     105             :   }
     106             : 
     107           5 :   matcher = wrapMatcher(matcher);
     108           0 :   if (skip != null && skip != false) {
     109             :     String message;
     110           0 :     if (skip is String) {
     111           0 :       message = "Skip expect: $skip";
     112             :     } else if (reason != null) {
     113           0 :       message = "Skip expect ($reason).";
     114             :     } else {
     115           0 :       var description = new StringDescription().addDescriptionOf(matcher);
     116           0 :       message = "Skip expect ($description).";
     117             :     }
     118             : 
     119           0 :     Invoker.current.skip(message);
     120           0 :     return _emptyFuture;
     121             :   }
     122             : 
     123           5 :   if (matcher is AsyncMatcher) {
     124             :     // Avoid async/await so that expect() throws synchronously when possible.
     125           1 :     var result = matcher.matchAsync(actual);
     126           1 :     expect(
     127             :         result,
     128           2 :         anyOf([
     129           1 :           equals(null),
     130           1 :           new isInstanceOf<Future>(),
     131           1 :           new isInstanceOf<String>()
     132             :         ]),
     133             :         reason: "matchAsync() may only return a String, a Future, or null.");
     134             : 
     135           1 :     if (result is String) {
     136           0 :       fail(formatFailure(matcher, actual, result, reason: reason));
     137           1 :     } else if (result is Future) {
     138           0 :       Invoker.current.addOutstandingCallback();
     139           0 :       return result.then((realResult) {
     140             :         if (realResult == null) return;
     141           0 :         fail(formatFailure(matcher, actual, realResult, reason: reason));
     142           0 :       }).whenComplete(() {
     143             :         // Always remove this, in case the failure is caught and handled
     144             :         // gracefully.
     145           0 :         Invoker.current.removeOutstandingCallback();
     146             :       });
     147             :     }
     148             : 
     149           1 :     return _emptyFuture;
     150             :   }
     151             : 
     152           5 :   var matchState = {};
     153             :   try {
     154          10 :     if (matcher.matches(actual, matchState)) return _emptyFuture;
     155             :   } catch (e, trace) {
     156           0 :     reason ??= '$e at $trace';
     157             :   }
     158           0 :   fail(formatter(actual, matcher, reason, matchState, verbose));
     159           0 :   return _emptyFuture;
     160             : }
     161             : 
     162             : /// Convenience method for throwing a new [TestFailure] with the provided
     163             : /// [message].
     164           0 : void fail(String message) => throw new TestFailure(message);
     165             : 
     166             : // The default error formatter.
     167             : @Deprecated("Will be removed in 0.13.0.")
     168             : String formatFailure(Matcher expected, actual, String which, {String reason}) {
     169           0 :   var buffer = new StringBuffer();
     170           0 :   buffer.writeln(indent(prettyPrint(expected), first: 'Expected: '));
     171           0 :   buffer.writeln(indent(prettyPrint(actual), first: '  Actual: '));
     172           0 :   if (which.isNotEmpty) buffer.writeln(indent(which, first: '   Which: '));
     173           0 :   if (reason != null) buffer.writeln(reason);
     174           0 :   return buffer.toString();
     175             : }

Generated by: LCOV version 1.13