| Index: pkg/unittest/unittest.dart
 | 
| ===================================================================
 | 
| --- pkg/unittest/unittest.dart	(revision 14313)
 | 
| +++ pkg/unittest/unittest.dart	(working copy)
 | 
| @@ -1,906 +0,0 @@
 | 
| -// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
 | 
| -// for details. All rights reserved. Use of this source code is governed by a
 | 
| -// BSD-style license that can be found in the LICENSE file.
 | 
| -
 | 
| -/**
 | 
| - * A library for writing dart unit tests.
 | 
| - *
 | 
| - * To import this library, use the pub package manager.
 | 
| - * Create a pubspec.yaml file in your project and add
 | 
| - * a dependency on unittest with the following lines:
 | 
| - *     dependencies:
 | 
| - *       unittest:
 | 
| - *         sdk: unittest
 | 
| - *         
 | 
| - * Then run 'pub install' from your project directory or using
 | 
| - * the DartEditor.
 | 
| - *         
 | 
| - * Please see [Pub Getting Started](http://pub.dartlang.org/doc)
 | 
| - * for more details about the pub package manager.
 | 
| - *
 | 
| - * ##Concepts##
 | 
| - *
 | 
| - *  * Tests: Tests are specified via the top-level function [test], they can be
 | 
| - *    organized together using [group].
 | 
| - *  * Checks: Test expectations can be specified via [expect]
 | 
| - *  * Matchers: [expect] assertions are written declaratively using [Matcher]s
 | 
| - *  * Configuration: The framework can be adapted by calling [configure] with a
 | 
| - *    [Configuration].  Common configurations can be found in this package
 | 
| - *    under: 'dom\_config.dart' (deprecated), 'html\_config.dart' (for running
 | 
| - *    tests compiled to Javascript in a browser), and 'vm\_config.dart' (for
 | 
| - *    running native Dart tests on the VM).
 | 
| - *
 | 
| - * ##Examples##
 | 
| - *
 | 
| - * A trivial test:
 | 
| - *
 | 
| - *     import 'package:unittest/unittest.dart';
 | 
| - *     main() {
 | 
| - *       test('this is a test', () {
 | 
| - *         int x = 2 + 3;
 | 
| - *         expect(x, equals(5));
 | 
| - *       });
 | 
| - *     }
 | 
| - *
 | 
| - * Multiple tests:
 | 
| - *
 | 
| - *     import 'package:unittest/unittest.dart';
 | 
| - *     main() {
 | 
| - *       test('this is a test', () {
 | 
| - *         int x = 2 + 3;
 | 
| - *         expect(x, equals(5));
 | 
| - *       });
 | 
| - *       test('this is another test', () {
 | 
| - *         int x = 2 + 3;
 | 
| - *         expect(x, equals(5));
 | 
| - *       });
 | 
| - *     }
 | 
| - *
 | 
| - * Multiple tests, grouped by category:
 | 
| - *
 | 
| - *     import 'package:unittest/unittest.dart';
 | 
| - *     main() {
 | 
| - *       group('group A', () {
 | 
| - *         test('test A.1', () {
 | 
| - *           int x = 2 + 3;
 | 
| - *           expect(x, equals(5));
 | 
| - *         });
 | 
| - *         test('test A.2', () {
 | 
| - *           int x = 2 + 3;
 | 
| - *           expect(x, equals(5));
 | 
| - *         });
 | 
| - *       });
 | 
| - *       group('group B', () {
 | 
| - *         test('this B.1', () {
 | 
| - *           int x = 2 + 3;
 | 
| - *           expect(x, equals(5));
 | 
| - *         });
 | 
| - *       });
 | 
| - *     }
 | 
| - *
 | 
| - * Asynchronous tests: if callbacks expect between 0 and 2 positional arguments,
 | 
| - * depending on the suffix of expectAsyncX(). expectAsyncX() will wrap a
 | 
| - * function into a new callback and will not consider the test complete until
 | 
| - * that callback is run. A count argument can be provided to specify the number
 | 
| - * of times the callback should be called (the default is 1).
 | 
| - *
 | 
| - *     import 'package:unittest/unittest.dart';
 | 
| - *     import 'dart:isolate';
 | 
| - *     main() {
 | 
| - *       test('callback is executed once', () {
 | 
| - *         // wrap the callback of an asynchronous call with [expectAsync0] if
 | 
| - *         // the callback takes 0 arguments...
 | 
| - *         var timer = new Timer(0, (_) => expectAsync0(() {
 | 
| - *           int x = 2 + 3;
 | 
| - *           expect(x, equals(5));
 | 
| - *         }));
 | 
| - *       });
 | 
| - *
 | 
| - *       test('callback is executed twice', () {
 | 
| - *         var callback = (_) => expectAsync0(() {
 | 
| - *           int x = 2 + 3;
 | 
| - *           expect(x, equals(5));
 | 
| - *         }, count: 2); // <-- we can indicate multiplicity to [expectAsync0]
 | 
| - *         new Timer(0, callback);
 | 
| - *         new Timer(0, callback);
 | 
| - *       });
 | 
| - *     }
 | 
| - *
 | 
| - * expectAsyncX() will wrap the callback code in a try/catch handler to handle
 | 
| - * exceptions (treated as test failures). There may be times when the number of
 | 
| - * times a callback should be called is non-deterministic. In this case a dummy
 | 
| - * callback can be created with expectAsync0((){}) and this can be called from
 | 
| - * the real callback when it is finally complete. In this case the body of the
 | 
| - * callback should be protected within a call to guardAsync(); this will ensure
 | 
| - * that exceptions are properly handled.
 | 
| - *
 | 
| - * Note: due to some language limitations we have to use different functions
 | 
| - * depending on the number of positional arguments of the callback. In the
 | 
| - * future, we plan to expose a single `expectAsync` function that can be used
 | 
| - * regardless of the number of positional arguments. This requires new langauge
 | 
| - * features or fixes to the current spec (e.g. see
 | 
| - * [Issue 2706](http://dartbug.com/2706)).
 | 
| - *
 | 
| - * Meanwhile, we plan to add this alternative API for callbacks of more than 2
 | 
| - * arguments or that take named parameters. (this is not implemented yet,
 | 
| - * but will be coming here soon).
 | 
| - *
 | 
| - *     import 'package:unittest/unittest.dart';
 | 
| - *     import 'dart:isolate';
 | 
| - *     main() {
 | 
| - *       test('callback is executed', () {
 | 
| - *         // indicate ahead of time that an async callback is expected.
 | 
| - *         var async = startAsync();
 | 
| - *         new Timer(0, (_) {
 | 
| - *           // Guard the body of the callback, so errors are propagated
 | 
| - *           // correctly.
 | 
| - *           guardAsync(() {
 | 
| - *             int x = 2 + 3;
 | 
| - *             expect(x, equals(5));
 | 
| - *           });
 | 
| - *           // indicate that the asynchronous callback was invoked.
 | 
| - *           async.complete();
 | 
| - *         });
 | 
| - *       });
 | 
| - *     }
 | 
| - *
 | 
| - */
 | 
| -library unittest;
 | 
| -
 | 
| -import 'dart:isolate';
 | 
| -
 | 
| -part 'collection_matchers.dart';
 | 
| -part 'config.dart';
 | 
| -part 'core_matchers.dart';
 | 
| -part 'description.dart';
 | 
| -part 'expect.dart';
 | 
| -part 'future_matchers.dart';
 | 
| -part 'interfaces.dart';
 | 
| -part 'map_matchers.dart';
 | 
| -part 'matcher.dart';
 | 
| -part 'mock.dart';
 | 
| -part 'numeric_matchers.dart';
 | 
| -part 'operator_matchers.dart';
 | 
| -part 'string_matchers.dart';
 | 
| -part 'test_case.dart';
 | 
| -
 | 
| -/** [Configuration] used by the unittest library. */
 | 
| -Configuration _config = null;
 | 
| -
 | 
| -Configuration get config => _config;
 | 
| -
 | 
| -/**
 | 
| - * Set the [Configuration] used by the unittest library. Returns any
 | 
| - * previous configuration.
 | 
| - * TODO: consider deprecating in favor of a setter now we have a getter.
 | 
| - */
 | 
| -Configuration configure(Configuration config) {
 | 
| -  Configuration _oldConfig = _config;
 | 
| -  _config = config;
 | 
| -  return _oldConfig;
 | 
| -}
 | 
| -
 | 
| -void logMessage(String message) => _config.logMessage(message);
 | 
| -
 | 
| -/**
 | 
| - * Description text of the current test group. If multiple groups are nested,
 | 
| - * this will contain all of their text concatenated.
 | 
| - */
 | 
| -String _currentGroup = '';
 | 
| -
 | 
| -/** Separator used between group names and test names. */
 | 
| -String groupSep = ' ';
 | 
| -
 | 
| -/** Tests executed in this suite. */
 | 
| -List<TestCase> _tests;
 | 
| -
 | 
| -/** Get the list of tests. */
 | 
| -get testCases => _tests;
 | 
| -
 | 
| -/**
 | 
| - * Callback used to run tests. Entrypoints can replace this with their own
 | 
| - * if they want.
 | 
| - */
 | 
| -Function _testRunner;
 | 
| -
 | 
| -/** Setup function called before each test in a group */
 | 
| -Function _testSetup;
 | 
| -
 | 
| -/** Teardown function called after each test in a group */
 | 
| -Function _testTeardown;
 | 
| -
 | 
| -/** Current test being executed. */
 | 
| -int _currentTest = 0;
 | 
| -
 | 
| -/** Whether the framework is in an initialized state. */
 | 
| -bool _initialized = false;
 | 
| -
 | 
| -String _uncaughtErrorMessage = null;
 | 
| -
 | 
| -/** Test case result strings. */
 | 
| -// TODO(gram) we should change these constants to use a different string
 | 
| -// (so that writing 'FAIL' in the middle of a test doesn't
 | 
| -// imply that the test fails). We can't do it without also changing
 | 
| -// the testrunner and test.dart though.
 | 
| -const PASS  = 'pass';
 | 
| -const FAIL  = 'fail';
 | 
| -const ERROR = 'error';
 | 
| -
 | 
| -/** If set, then all other test cases will be ignored. */
 | 
| -TestCase _soloTest;
 | 
| -
 | 
| -/**
 | 
| - * A map that can be used to communicate state between a test driver
 | 
| - * or main() function and the tests, particularly when these two
 | 
| - * are otherwise independent. For example, a test driver that starts
 | 
| - * an HTTP server and then runs tests that access that server could use
 | 
| - * this as a way of communicating the server port to the tests.
 | 
| - */
 | 
| -Map testState = {};
 | 
| -
 | 
| -/**
 | 
| - * (Deprecated) Evaluates the [function] and validates that it throws an
 | 
| - * exception. If [callback] is provided, then it will be invoked with the
 | 
| - * thrown exception. The callback may do any validation it wants. In addition,
 | 
| - * if it returns `false`, that also indicates an expectation failure.
 | 
| - */
 | 
| -void expectThrow(function, [bool callback(exception)]) {
 | 
| -  bool threw = false;
 | 
| -  try {
 | 
| -    function();
 | 
| -  } catch (e) {
 | 
| -    threw = true;
 | 
| -
 | 
| -    // Also let the callback look at it.
 | 
| -    if (callback != null) {
 | 
| -      var result = callback(e);
 | 
| -
 | 
| -      // If the callback explicitly returned false, treat that like an
 | 
| -      // expectation too. (If it returns null, though, don't.)
 | 
| -      if (result == false) {
 | 
| -        fail('Exception:\n$e\ndid not match expectation.');
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  if (threw != true) fail('An expected exception was not thrown.');
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Creates a new test case with the given description and body. The
 | 
| - * description will include the descriptions of any surrounding group()
 | 
| - * calls.
 | 
| - */
 | 
| -void test(String spec, TestFunction body) {
 | 
| -  ensureInitialized();
 | 
| -  _tests.add(new TestCase(_tests.length + 1, _fullSpec(spec), body, 0));
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * (Deprecated) Creates a new async test case with the given description
 | 
| - * and body. The description will include the descriptions of any surrounding
 | 
| - * group() calls.
 | 
| - */
 | 
| -// TODO(sigmund): deprecate this API
 | 
| -void asyncTest(String spec, int callbacks, TestFunction body) {
 | 
| -  ensureInitialized();
 | 
| -
 | 
| -  final testCase = new TestCase(
 | 
| -      _tests.length + 1, _fullSpec(spec), body, callbacks);
 | 
| -  _tests.add(testCase);
 | 
| -
 | 
| -  if (callbacks < 1) {
 | 
| -    testCase.error(
 | 
| -        'Async tests must wait for at least one callback ', '');
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Creates a new test case with the given description and body. The
 | 
| - * description will include the descriptions of any surrounding group()
 | 
| - * calls.
 | 
| - *
 | 
| - * "solo_" means that this will be the only test that is run. All other tests
 | 
| - * will be skipped. This is a convenience function to let you quickly isolate
 | 
| - * a single test by adding "solo_" before it to temporarily disable all other
 | 
| - * tests.
 | 
| - */
 | 
| -void solo_test(String spec, TestFunction body) {
 | 
| -  // TODO(rnystrom): Support multiple solos. If more than one test is solo-ed,
 | 
| -  // all of the solo-ed tests and none of the non-solo-ed ones should run.
 | 
| -  if (_soloTest != null) {
 | 
| -    throw new Exception('Only one test can be soloed right now.');
 | 
| -  }
 | 
| -
 | 
| -  ensureInitialized();
 | 
| -
 | 
| -  _soloTest = new TestCase(_tests.length + 1, _fullSpec(spec), body, 0);
 | 
| -  _tests.add(_soloTest);
 | 
| -}
 | 
| -
 | 
| -/** Sentinel value for [_SpreadArgsHelper]. */
 | 
| -class _Sentinel {
 | 
| -  const _Sentinel();
 | 
| -}
 | 
| -
 | 
| -/** Simulates spread arguments using named arguments. */
 | 
| -// TODO(sigmund): remove this class and simply use a closure with named
 | 
| -// arguments (if still applicable).
 | 
| -class _SpreadArgsHelper {
 | 
| -  Function _callback;
 | 
| -  int _expectedCalls;
 | 
| -  int _actualCalls = 0;
 | 
| -  int _testNum;
 | 
| -  TestCase _testCase;
 | 
| -  Function _shouldCallBack;
 | 
| -  Function _isDone;
 | 
| -  static const _sentinel = const _Sentinel();
 | 
| -
 | 
| -  _init(Function callback, Function shouldCallBack, Function isDone,
 | 
| -       [expectedCalls = 0]) {
 | 
| -    ensureInitialized();
 | 
| -    if (!(_currentTest >= 0 &&
 | 
| -           _currentTest < _tests.length &&
 | 
| -           _tests[_currentTest] != null)) {
 | 
| -      print("No valid test, did you forget to run your test inside a call "
 | 
| -          "to test()?");
 | 
| -    }
 | 
| -    assert(_currentTest >= 0 &&
 | 
| -           _currentTest < _tests.length &&
 | 
| -           _tests[_currentTest] != null);
 | 
| -    _callback = callback;
 | 
| -    _shouldCallBack = shouldCallBack;
 | 
| -    _isDone = isDone;
 | 
| -    _expectedCalls = expectedCalls;
 | 
| -    _testNum = _currentTest;
 | 
| -    _testCase = _tests[_currentTest];
 | 
| -    if (expectedCalls > 0) {
 | 
| -      _testCase.callbackFunctionsOutstanding++;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  _SpreadArgsHelper(callback, shouldCallBack, isDone) {
 | 
| -    _init(callback, shouldCallBack, isDone);
 | 
| -  }
 | 
| -
 | 
| -  _SpreadArgsHelper.fixedCallCount(callback, expectedCalls) {
 | 
| -    _init(callback, _checkCallCount, _allCallsDone, expectedCalls);
 | 
| -  }
 | 
| -
 | 
| -  _SpreadArgsHelper.variableCallCount(callback, isDone) {
 | 
| -    _init(callback, _always, isDone, 1);
 | 
| -   }
 | 
| -
 | 
| -  _SpreadArgsHelper.optionalCalls(callback) {
 | 
| -    _init(callback, _always, () => false, 0);
 | 
| -   }
 | 
| -
 | 
| -  _after() {
 | 
| -    if (_isDone()) {
 | 
| -      _handleCallbackFunctionComplete();
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  _allCallsDone() => _actualCalls == _expectedCalls;
 | 
| -
 | 
| -  _always() {
 | 
| -    // Always run except if the test is done.
 | 
| -    if (_testCase.isComplete) {
 | 
| -      _testCase.error(
 | 
| -          'Callback called after already being marked as done ($_actualCalls).',
 | 
| -          '');
 | 
| -      return false;
 | 
| -    } else {
 | 
| -      return true;
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel,
 | 
| -          arg3 = _sentinel, arg4 = _sentinel]) {
 | 
| -    return guardAsync(() {
 | 
| -      ++_actualCalls;
 | 
| -      if (!_shouldCallBack()) {
 | 
| -        return;
 | 
| -      } else if (arg0 == _sentinel) {
 | 
| -        return _callback();
 | 
| -      } else if (arg1 == _sentinel) {
 | 
| -        return _callback(arg0);
 | 
| -      } else if (arg2 == _sentinel) {
 | 
| -        return _callback(arg0, arg1);
 | 
| -      } else if (arg3 == _sentinel) {
 | 
| -        return _callback(arg0, arg1, arg2);
 | 
| -      } else if (arg4 == _sentinel) {
 | 
| -        return _callback(arg0, arg1, arg2, arg3);
 | 
| -      } else {
 | 
| -        _testCase.error(
 | 
| -           'unittest lib does not support callbacks with more than'
 | 
| -              ' 4 arguments.',
 | 
| -           '');
 | 
| -      }
 | 
| -    },
 | 
| -    _after, _testNum);
 | 
| -  }
 | 
| -
 | 
| -  invoke0() {
 | 
| -    return guardAsync(
 | 
| -        () {
 | 
| -          ++_actualCalls;
 | 
| -          if (_shouldCallBack()) {
 | 
| -            return _callback();
 | 
| -          }
 | 
| -        },
 | 
| -        _after, _testNum);
 | 
| -  }
 | 
| -
 | 
| -  invoke1(arg1) {
 | 
| -    return guardAsync(
 | 
| -        () {
 | 
| -          ++_actualCalls;
 | 
| -          if (_shouldCallBack()) {
 | 
| -            return _callback(arg1);
 | 
| -          }
 | 
| -        },
 | 
| -        _after, _testNum);
 | 
| -  }
 | 
| -
 | 
| -  invoke2(arg1, arg2) {
 | 
| -    return guardAsync(
 | 
| -        () {
 | 
| -          ++_actualCalls;
 | 
| -          if (_shouldCallBack()) {
 | 
| -            return _callback(arg1, arg2);
 | 
| -          }
 | 
| -        },
 | 
| -        _after, _testNum);
 | 
| -  }
 | 
| -
 | 
| -  /** Returns false if we exceded the number of expected calls. */
 | 
| -  bool _checkCallCount() {
 | 
| -    if (_actualCalls > _expectedCalls) {
 | 
| -      _testCase.error('Callback called more times than expected '
 | 
| -             '($_actualCalls > $_expectedCalls).', '');
 | 
| -      return false;
 | 
| -    }
 | 
| -    return true;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Indicate that [callback] is expected to be called a [count] number of times
 | 
| - * (by default 1). The unittest framework will wait for the callback to run the
 | 
| - * specified [count] times before it continues with the following test.  Using
 | 
| - * [_expectAsync] will also ensure that errors that occur within [callback] are
 | 
| - * tracked and reported. [callback] should take between 0 and 4 positional
 | 
| - * arguments (named arguments are not supported here).
 | 
| - */
 | 
| -Function _expectAsync(Function callback, [int count = 1]) {
 | 
| -  return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Indicate that [callback] is expected to be called a [count] number of times
 | 
| - * (by default 1). The unittest framework will wait for the callback to run the
 | 
| - * specified [count] times before it continues with the following test.  Using
 | 
| - * [expectAsync0] will also ensure that errors that occur within [callback] are
 | 
| - * tracked and reported. [callback] should take 0 positional arguments (named
 | 
| - * arguments are not supported).
 | 
| - */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function expectAsync0(Function callback, [int count = 1]) {
 | 
| -  return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke0;
 | 
| -}
 | 
| -
 | 
| -/** Like [expectAsync0] but [callback] should take 1 positional argument. */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function expectAsync1(Function callback, {int count: 1}) {
 | 
| -  return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke1;
 | 
| -}
 | 
| -
 | 
| -/** Like [expectAsync0] but [callback] should take 2 positional arguments. */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function expectAsync2(Function callback, [int count = 1]) {
 | 
| -  return new _SpreadArgsHelper.fixedCallCount(callback, count).invoke2;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Indicate that [callback] is expected to be called until [isDone] returns
 | 
| - * true. The unittest framework checks [isDone] after each callback and only
 | 
| - * when it returns true will it continue with the following test. Using
 | 
| - * [expectAsyncUntil] will also ensure that errors that occur within
 | 
| - * [callback] are tracked and reported. [callback] should take between 0 and
 | 
| - * 4 positional arguments (named arguments are not supported).
 | 
| - */
 | 
| -Function _expectAsyncUntil(Function callback, Function isDone) {
 | 
| -  return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Indicate that [callback] is expected to be called until [isDone] returns
 | 
| - * true. The unittest framework check [isDone] after each callback and only
 | 
| - * when it returns true will it continue with the following test. Using
 | 
| - * [expectAsyncUntil0] will also ensure that errors that occur within
 | 
| - * [callback] are tracked and reported. [callback] should take 0 positional
 | 
| - * arguments (named arguments are not supported).
 | 
| - */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function expectAsyncUntil0(Function callback, Function isDone) {
 | 
| -  return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke0;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Like [expectAsyncUntil0] but [callback] should take 1 positional argument.
 | 
| - */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function expectAsyncUntil1(Function callback, Function isDone) {
 | 
| -  return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke1;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Like [expectAsyncUntil0] but [callback] should take 2 positional arguments.
 | 
| - */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function expectAsyncUntil2(Function callback, Function isDone) {
 | 
| -  return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Wraps the [callback] in a new function and returns that function. The new
 | 
| - * function will be able to handle exceptions by directing them to the correct
 | 
| - * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
 | 
| - * might optionally be called but may never be called during the test.
 | 
| - * [callback] should take between 0 and 4 positional arguments (named arguments
 | 
| - * are not supported).
 | 
| - */
 | 
| -Function _protectAsync(Function callback) {
 | 
| -  return new _SpreadArgsHelper.optionalCalls(callback).invoke;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Wraps the [callback] in a new function and returns that function. The new
 | 
| - * function will be able to handle exceptions by directing them to the correct
 | 
| - * test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
 | 
| - * might optionally be called but may never be called during the test.
 | 
| - * [callback] should take 0 positional arguments (named arguments are not
 | 
| - * supported).
 | 
| - */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function protectAsync0(Function callback) {
 | 
| -  return new _SpreadArgsHelper.optionalCalls(callback).invoke0;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Like [protectAsync0] but [callback] should take 1 positional argument.
 | 
| - */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function protectAsync1(Function callback) {
 | 
| -  return new _SpreadArgsHelper.optionalCalls(callback).invoke1;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Like [protectAsync0] but [callback] should take 2 positional arguments.
 | 
| - */
 | 
| -// TODO(sigmund): deprecate this API when issue 2706 is fixed.
 | 
| -Function protectAsync2(Function callback) {
 | 
| -  return new _SpreadArgsHelper.optionalCalls(callback).invoke2;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Creates a new named group of tests. Calls to group() or test() within the
 | 
| - * body of the function passed to this will inherit this group's description.
 | 
| - */
 | 
| -void group(String description, void body()) {
 | 
| -  ensureInitialized();
 | 
| -  // Concatenate the new group.
 | 
| -  final parentGroup = _currentGroup;
 | 
| -  if (_currentGroup != '') {
 | 
| -    // Add a space.
 | 
| -    _currentGroup = '$_currentGroup$groupSep$description';
 | 
| -  } else {
 | 
| -    // The first group.
 | 
| -    _currentGroup = description;
 | 
| -  }
 | 
| -
 | 
| -  // Groups can be nested, so we need to preserve the current
 | 
| -  // settings for test setup/teardown.
 | 
| -  Function parentSetup = _testSetup;
 | 
| -  Function parentTeardown = _testTeardown;
 | 
| -
 | 
| -  try {
 | 
| -    _testSetup = null;
 | 
| -    _testTeardown = null;
 | 
| -    body();
 | 
| -  } catch (e, trace) {
 | 
| -    var stack = (trace == null) ? '' : ': ${trace.toString()}';
 | 
| -    _uncaughtErrorMessage = "${e.toString()}$stack";
 | 
| -  } finally {
 | 
| -    // Now that the group is over, restore the previous one.
 | 
| -    _currentGroup = parentGroup;
 | 
| -    _testSetup = parentSetup;
 | 
| -    _testTeardown = parentTeardown;
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Register a [setUp] function for a test [group]. This function will
 | 
| - * be called before each test in the group is run. Note that if groups
 | 
| - * are nested only the most locally scoped [setUp] function will be run.
 | 
| - * [setUp] and [tearDown] should be called within the [group] before any
 | 
| - * calls to [test].
 | 
| - */
 | 
| -void setUp(Function setupTest) {
 | 
| -  _testSetup = setupTest;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Register a [tearDown] function for a test [group]. This function will
 | 
| - * be called after each test in the group is run. Note that if groups
 | 
| - * are nested only the most locally scoped [tearDown] function will be run.
 | 
| - * [setUp] and [tearDown] should be called within the [group] before any
 | 
| - * calls to [test].
 | 
| - */
 | 
| -void tearDown(Function teardownTest) {
 | 
| -  _testTeardown = teardownTest;
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Called when one of the callback functions is done with all expected
 | 
| - * calls.
 | 
| - */
 | 
| -void _handleCallbackFunctionComplete() {
 | 
| -  // TODO (gram): we defer this to give the nextBatch recursive
 | 
| -  // stack a chance to unwind. This is a temporary hack but
 | 
| -  // really a bunch of code here needs to be fixed. We have a
 | 
| -  // single array that is being iterated through by nextBatch(),
 | 
| -  // which is recursively invoked in the case of async tests that
 | 
| -  // run synchronously. Bad things can then happen.
 | 
| -  _defer(() {
 | 
| -    if (_currentTest < _tests.length) {
 | 
| -      final testCase = _tests[_currentTest];
 | 
| -      --testCase.callbackFunctionsOutstanding;
 | 
| -      if (testCase.callbackFunctionsOutstanding < 0) {
 | 
| -        // TODO(gram): Check: Can this even happen?
 | 
| -        testCase.error(
 | 
| -            'More calls to _handleCallbackFunctionComplete() than expected.',
 | 
| -             '');
 | 
| -      } else if (testCase.callbackFunctionsOutstanding == 0) {
 | 
| -        if (!testCase.isComplete) {
 | 
| -          testCase.pass();
 | 
| -        }
 | 
| -        _nextTestCase();
 | 
| -      }
 | 
| -    }
 | 
| -  });
 | 
| -}
 | 
| -
 | 
| -/** Advance to the next test case. */
 | 
| -void _nextTestCase() {
 | 
| -  _currentTest++;
 | 
| -  _testRunner();
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Temporary hack: expose old API.
 | 
| - * TODO(gram) remove this when WebKit tests are working with new framework
 | 
| - */
 | 
| -void callbackDone() {
 | 
| -  _handleCallbackFunctionComplete();
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Utility function that can be used to notify the test framework that an
 | 
| - *  error was caught outside of this library.
 | 
| - */
 | 
| -void _reportTestError(String msg, String trace) {
 | 
| - if (_currentTest < _tests.length) {
 | 
| -    final testCase = _tests[_currentTest];
 | 
| -    testCase.error(msg, trace);
 | 
| -    if (testCase.callbackFunctionsOutstanding > 0) {
 | 
| -      _nextTestCase();
 | 
| -    }
 | 
| -  } else {
 | 
| -    _uncaughtErrorMessage = "$msg: $trace";
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/** Runs [callback] at the end of the event loop. */
 | 
| -_defer(void callback()) {
 | 
| -  // Exploit isolate ports as a platform-independent mechanism to queue a
 | 
| -  // message at the end of the event loop.
 | 
| -  // TODO(sigmund): expose this functionality somewhere in our libraries.
 | 
| -  final port = new ReceivePort();
 | 
| -  port.receive((msg, reply) {
 | 
| -    callback();
 | 
| -    port.close();
 | 
| -  });
 | 
| -  port.toSendPort().send(null, null);
 | 
| -}
 | 
| -
 | 
| -rerunTests() {
 | 
| -  _uncaughtErrorMessage = null;
 | 
| -  _initialized = true; // We don't want to reset the test array.
 | 
| -  runTests();
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Filter the tests. [testFilter] can be a [RegExp], a [String] or a
 | 
| - * predicate function. This is different to enabling/disabling tests
 | 
| - * in that it removes the tests completely.
 | 
| - */
 | 
| -void filterTests(testFilter) {
 | 
| -  var filterFunction;
 | 
| -  if (testFilter is String) {
 | 
| -    RegExp re = new RegExp(testFilter);
 | 
| -    filterFunction = (t) => re.hasMatch(t.description);
 | 
| -  } else if (testFilter is RegExp) {
 | 
| -    filterFunction = (t) => testFilter.hasMatch(t.description);
 | 
| -  } else if (testFilter is Function) {
 | 
| -    filterFunction = testFilter;
 | 
| -  }
 | 
| -  _tests = _tests.filter(filterFunction);
 | 
| -}
 | 
| -
 | 
| -/** Runs all queued tests, one at a time. */
 | 
| -runTests() {
 | 
| -  _currentTest = 0;
 | 
| -  _currentGroup = '';
 | 
| -
 | 
| -  // If we are soloing a test, remove all the others.
 | 
| -  if (_soloTest != null) {
 | 
| -    filterTests((t) => t == _soloTest);
 | 
| -  }
 | 
| -
 | 
| -  _config.onStart();
 | 
| -
 | 
| -  _defer(() {
 | 
| -    _testRunner();
 | 
| -  });
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update
 | 
| - * the [_currentTest] status accordingly.
 | 
| - */
 | 
| -guardAsync(tryBody, [finallyBody, testNum = -1]) {
 | 
| -  if (testNum < 0) testNum = _currentTest;
 | 
| -  try {
 | 
| -    return tryBody();
 | 
| -  } catch (e, trace) {
 | 
| -    _registerException(testNum, e, trace);
 | 
| -  } finally {
 | 
| -    if (finallyBody != null) finallyBody();
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Registers that an exception was caught for the current test.
 | 
| - */
 | 
| -registerException(e, [trace]) {
 | 
| -  _registerException(_currentTest, e, trace);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Registers that an exception was caught for the current test.
 | 
| - */
 | 
| -_registerException(testNum, e, [trace]) {
 | 
| -  trace = trace == null ? '' : trace.toString();
 | 
| -  if (_tests[testNum].result == null) {
 | 
| -    String message = (e is ExpectException) ? e.message : 'Caught $e';
 | 
| -    _tests[testNum].fail(message, trace);
 | 
| -  } else {
 | 
| -    _tests[testNum].error('Caught $e', trace);
 | 
| -  }
 | 
| -  if (testNum == _currentTest &&
 | 
| -      _tests[testNum].callbackFunctionsOutstanding > 0) {
 | 
| -    _nextTestCase();
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Runs a batch of tests, yielding whenever an asynchronous test starts
 | 
| - * running. Tests will resume executing when such asynchronous test calls
 | 
| - * [done] or if it fails with an exception.
 | 
| - */
 | 
| -_nextBatch() {
 | 
| -  while (_currentTest < _tests.length) {
 | 
| -    final testCase = _tests[_currentTest];
 | 
| -    guardAsync(() {
 | 
| -      testCase.run();
 | 
| -      if (!testCase.isComplete && testCase.callbackFunctionsOutstanding == 0) {
 | 
| -        testCase.pass();
 | 
| -      }
 | 
| -    }, null, _currentTest);
 | 
| -
 | 
| -    if (!testCase.isComplete &&
 | 
| -        testCase.callbackFunctionsOutstanding > 0) return;
 | 
| -    _currentTest++;
 | 
| -  }
 | 
| -
 | 
| -  _completeTests();
 | 
| -}
 | 
| -
 | 
| -/** Publish results on the page and notify controller. */
 | 
| -_completeTests() {
 | 
| -  if (!_initialized) return;
 | 
| -  int testsPassed_ = 0;
 | 
| -  int testsFailed_ = 0;
 | 
| -  int testsErrors_ = 0;
 | 
| -
 | 
| -  for (TestCase t in _tests) {
 | 
| -    switch (t.result) {
 | 
| -      case PASS:  testsPassed_++; break;
 | 
| -      case FAIL:  testsFailed_++; break;
 | 
| -      case ERROR: testsErrors_++; break;
 | 
| -    }
 | 
| -  }
 | 
| -  _config.onDone(testsPassed_, testsFailed_, testsErrors_, _tests,
 | 
| -      _uncaughtErrorMessage);
 | 
| -  _initialized = false;
 | 
| -}
 | 
| -
 | 
| -String _fullSpec(String spec) {
 | 
| -  if (spec === null) return '$_currentGroup';
 | 
| -  return _currentGroup != '' ? '$_currentGroup$groupSep$spec' : spec;
 | 
| -}
 | 
| -
 | 
| -void fail(String message) {
 | 
| -  throw new ExpectException(message);
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * Lazily initializes the test library if not already initialized.
 | 
| - */
 | 
| -ensureInitialized() {
 | 
| -  if (_initialized) {
 | 
| -    return;
 | 
| -  }
 | 
| -  _initialized = true;
 | 
| -
 | 
| -  _tests = <TestCase>[];
 | 
| -  _testRunner = _nextBatch;
 | 
| -  _uncaughtErrorMessage = null;
 | 
| -
 | 
| -  if (_config == null) {
 | 
| -    _config = new Configuration();
 | 
| -  }
 | 
| -  _config.onInit();
 | 
| -
 | 
| -  if (_config.autoStart) {
 | 
| -    // Immediately queue the suite up. It will run after a timeout (i.e. after
 | 
| -    // main() has returned).
 | 
| -    _defer(runTests);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/** Select a solo test by ID. */
 | 
| -void setSoloTest(int id) {
 | 
| -  for (var i = 0; i < _tests.length; i++) {
 | 
| -    if (_tests[i].id == id) {
 | 
| -      _soloTest = _tests[i];
 | 
| -      break;
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/** Enable/disable a test by ID. */
 | 
| -void _setTestEnabledState(int testId, bool state) {
 | 
| -  // Try fast path first.
 | 
| -  if (_tests.length > testId && _tests[testId].id == testId) {
 | 
| -    _tests[testId].enabled = state;
 | 
| -  } else {
 | 
| -    for (var i = 0; i < _tests.length; i++) {
 | 
| -      if (_tests[i].id == testId) {
 | 
| -        _tests[i].enabled = state;
 | 
| -        break;
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -/** Enable a test by ID. */
 | 
| -void enableTest(int testId) => _setTestEnabledState(testId, true);
 | 
| -
 | 
| -/** Disable a test by ID. */
 | 
| -void disableTest(int testId) => _setTestEnabledState(testId, false);
 | 
| -
 | 
| -/** Signature for a test function. */
 | 
| -typedef void TestFunction();
 | 
| 
 |