// Copyright (c) 2013, 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.

// TODO(nweiz): Add support for calling [schedule] while the schedule is already
// running.
// TODO(nweiz): Port the non-Pub-specific scheduled test libraries from Pub.
/// A package for writing readable tests of asynchronous behavior.
///
/// ## Installing ##
///
/// Use [pub][] to install this package. Add the following to your
/// `pubspec.yaml` file.
///
///     dependencies:
///       scheduled_test: any
///
/// Then run `pub install`.
///
/// For more information, see the
/// [scheduled_test package on pub.dartlang.org][pkg].
///
/// This package works by building up a queue of asynchronous tasks called a
/// "schedule", then executing those tasks in order. This allows the tests to
/// read like synchronous, linear code, despite executing asynchronously.
///
/// The `scheduled_test` package is built on top of `unittest`, and should be
/// imported instead of `unittest`. It provides its own version of [group],
/// [test], and [setUp], and re-exports most other APIs from unittest.
///
/// To schedule a task, call the [schedule] function. For example:
///
///     import 'package:scheduled_test/scheduled_test.dart';
///
///     void main() {
///       test('writing to a file and reading it back should work', () {
///         schedule(() {
///           // The schedule won't proceed until the returned Future has
///           // completed.
///           return new File("output.txt").writeAsString("contents");
///         });
///
///         schedule(() {
///           return new File("output.txt").readAsString().then((contents) {
///             // The normal unittest matchers can still be used.
///             expect(contents, equals("contents"));
///           });
///         });
///       });
///     }
///
/// ## Setting Up and Tearing Down
///
/// The `scheduled_test` package defines its own [setUp] method that works just
/// like the one in `unittest`. Tasks can be scheduled in [setUp]; they'll be
/// run before the tasks scheduled by tests in that group. [currentSchedule] is
/// also set in the [setUp] callback.
///
/// This package doesn't have an explicit `tearDown` method. Instead, the
/// [currentSchedule.onComplete] and [currentSchedule.onException] task queues
/// can have tasks scheduled during [setUp]. For example:
///
///     import 'package:scheduled_test/scheduled_test.dart';
///
///     void main() {
///       var tempDir;
///       setUp(() {
///         schedule(() {
///           return createTempDir().then((dir) {
///             tempDir = dir;
///           });
///         });
///
///         currentSchedule.onComplete.schedule(() => deleteDir(tempDir));
///       });
///
///       // ...
///     }
///
/// ## Passing Values Between Tasks
///
/// It's often useful to use values computed in one task in other tasks that are
/// scheduled afterwards. There are two ways to do this. The most
/// straightforward is just to define a local variable and assign to it. For
/// example:
///
///     import 'package:scheduled_test/scheduled_test.dart';
///
///     void main() {
///       test('computeValue returns 12', () {
///         var value;
///
///         schedule(() {
///           return computeValue().then((computedValue) {
///             value = computedValue;
///           });
///         });
///
///         schedule(() => expect(value, equals(12)));
///       });
///     }
///
/// However, this doesn't scale well, especially when you start factoring out
/// calls to [schedule] into library methods. For that reason, [schedule]
/// returns a [Future] that will complete to the same value as the return
/// value of the task. For example:
///
///     import 'package:scheduled_test/scheduled_test.dart';
///
///     void main() {
///       test('computeValue returns 12', () {
///         var valueFuture = schedule(() => computeValue());
///         schedule(() {
///           valueFuture.then((value) => expect(value, equals(12)));
///         });
///       });
///     }
///
/// ## Out-of-Band Callbacks
///
/// Sometimes your tests will have callbacks that don't fit into the schedule.
/// It's important that errors in these callbacks are still registered, though,
/// and that [Schedule.onException] and [Schedule.onComplete] still run after
/// they finish. When using `unittest`, you wrap these callbacks with
/// `expectAsyncN`; when using `scheduled_test`, you use [wrapAsync] or
/// [wrapFuture].
///
/// [wrapAsync] has two important functions. First, any errors that occur in it
/// will be passed into the [Schedule] instead of causing the whole test to
/// crash. They can then be handled by [Schedule.onException] and
/// [Schedule.onComplete]. Second, a task queue isn't considered finished until
/// all of its [wrapAsync]-wrapped functions have been called. This ensures that
/// [Schedule.onException] and [Schedule.onComplete] will always run after all
/// the test code in the main queue.
///
/// Note that the [completes], [completion], and [throws] matchers use
/// [wrapAsync] internally, so they're safe to use in conjunction with scheduled
/// tests.
///
/// Here's an example of a test using [wrapAsync] to catch errors thrown in the
/// callback of a fictional `startServer` function:
///
///     import 'package:scheduled_test/scheduled_test.dart';
///
///     void main() {
///       test('sendRequest sends a request', () {
///         startServer(wrapAsync((request) {
///           expect(request.body, equals('payload'));
///           request.response.close();
///         }));
///
///         schedule(() => sendRequest('payload'));
///       });
///     }
///
/// [wrapFuture] works similarly to [wrapAsync], but instead of wrapping a
/// single callback it wraps a whole [Future] chain. Like [wrapAsync], it
/// ensures that the task queue doesn't complete until the out-of-band chain has
/// finished, and that any errors in the chain are piped back into the scheduled
/// test. For example:
///
///     import 'package:scheduled_test/scheduled_test.dart';
///
///     void main() {
///       test('sendRequest sends a request', () {
///         wrapFuture(server.nextRequest.then((request) {
///           expect(request.body, equals('payload'));
///           expect(request.headers['content-type'], equals('text/plain'));
///         }));
///
///         schedule(() => sendRequest('payload'));
///       });
///     }
///
/// ## Timeouts
///
/// `scheduled_test` has a built-in timeout of 30 seconds (configurable via
/// [Schedule.timeout]). This timeout is aware of the structure of the schedule;
/// this means that it will reset for each task in a queue, when moving between
/// queues, or almost any other sort of interaction with [currentSchedule]. As
/// long as the [Schedule] knows your test is making some sort of progress, it
/// won't time out.
///
/// If a single task might take a long time, you can also manually tell the
/// [Schedule] that it's making progress by calling [Schedule.heartbeat], which
/// will reset the timeout whenever it's called.
///
/// [pub]: http://pub.dartlang.org
/// [pkg]: http://pub.dartlang.org/packages/scheduled_test
library scheduled_test;

import 'dart:async';

import 'package:unittest/unittest.dart' as unittest;

import 'src/schedule.dart';
import 'src/schedule_error.dart';
import 'src/utils.dart';

export 'package:unittest/matcher.dart' hide completes, completion;
export 'package:unittest/unittest.dart' show
    Configuration, logMessage, expectThrow;

export 'src/schedule.dart';
export 'src/schedule_error.dart';
export 'src/scheduled_future_matchers.dart';
export 'src/task.dart';

/// The [Schedule] for the current test. This is used to add new tasks and
/// inspect the state of the schedule.
///
/// This is `null` when there's no test currently running.
Schedule get currentSchedule => _currentSchedule;
Schedule _currentSchedule;

/// The user-provided setUp function. This is set for each test during
/// `unittest.setUp`.
Function _setUpFn;

/// Creates a new test case with the given description and body. This has the
/// same semantics as [unittest.test].
void test(String description, void body()) =>
  _test(description, body, unittest.test);

/// Creates a new test case with the given description and body that will be the
/// only test run in this file. This has the same semantics as
/// [unittest.solo_test].
void solo_test(String description, void body()) =>
  _test(description, body, unittest.solo_test);

void _test(String description, void body(), Function testFn) {
  _ensureInitialized();
  _ensureSetUpForTopLevel();
  testFn(description, () {
    var asyncDone = unittest.expectAsync0(() {});
    return currentSchedule.run(() {
      if (_setUpFn != null) _setUpFn();
      body();
    }).then((_) {
      // If we got here, the test completed successfully so tell unittest so.
      asyncDone();
    }).catchError((e) {
      if (e is ScheduleError) {
        assert(e.schedule.errors.contains(e));
        assert(e.schedule == currentSchedule);
        unittest.registerException(e.schedule.errorString());
      } else {
        unittest.registerException(e);
      }
    });
  });
}

/// Whether or not the tests currently being defined are in a group. This is
/// only true when defining tests, not when executing them.
bool _inGroup = false;

/// Creates a new named group of tests. This has the same semantics as
/// [unittest.group].
void group(String description, void body()) {
  _ensureInitialized();
  _ensureSetUpForTopLevel();
  unittest.group(description, () {
    var wasInGroup = _inGroup;
    _inGroup = true;
    body();
    _inGroup = wasInGroup;
  });
}

/// Schedules a task, [fn], to run asynchronously as part of the main task queue
/// of [currentSchedule]. Tasks will be run in the order they're scheduled. If
/// [fn] returns a [Future], tasks after it won't be run until that [Future]
/// completes.
///
/// The return value will be completed once the scheduled task has finished
/// running. Its return value is the same as the return value of [fn], or the
/// value it completes to if it's a [Future].
///
/// If [description] is passed, it's used to describe the task for debugging
/// purposes when an error occurs.
///
/// If this is called when a task queue is currently running, it will run [fn]
/// on the next event loop iteration rather than adding it to a queue. The
/// current task will not complete until [fn] (and any [Future] it returns) has
/// finished running. Any errors in [fn] will automatically be handled.
Future schedule(fn(), [String description]) =>
  currentSchedule.tasks.schedule(fn, description);

/// Register a [setUp] function for a test [group]. This has the same semantics
/// as [unittest.setUp]. Tasks may be scheduled using [schedule] within
/// [setUpFn], and [currentSchedule] may be accessed as well.
///
/// Note that there is no associated [tearDown] function. Instead, tasks should
/// be scheduled for [currentSchedule.onComplete] or
/// [currentSchedule.onException]. These tasks will be run after each test's
/// schedule is completed.
void setUp(void setUpFn()) {
  _setUpScheduledTest(setUpFn);
}

/// Whether [unittest.setUp] has been called in the top level scope.
bool _setUpForTopLevel = false;

/// If we're in the top-level scope (that is, not in any [group]s) and
/// [unittest.setUp] hasn't been called yet, call it.
void _ensureSetUpForTopLevel() {
  if (_inGroup || _setUpForTopLevel) return;
  _setUpScheduledTest();
}

/// Registers callbacks for [unittest.setUp] and [unittest.tearDown] that set up
/// and tear down the scheduled test infrastructure.
void _setUpScheduledTest([void setUpFn()]) {
  if (!_inGroup) {
    _setUpForTopLevel = true;
    unittest.setUp(() {
      if (currentSchedule != null) {
        throw new StateError('There seems to be another scheduled test '
            'still running.');
      }
      _currentSchedule = new Schedule();
      if (_setUpFn != null) {
        var parentFn = _setUpFn;
        _setUpFn = () { parentFn(); setUpFn(); };
      } else {
        _setUpFn = setUpFn;
      }
    });
 
    unittest.tearDown(() {
      _currentSchedule = null;
      _setUpFn = null;
    });
  } else {
    unittest.setUp(() {
      if (currentSchedule == null) {
        throw new StateError('No schedule allocated.');
      } else if (_setUpFn != null) {
        var parentFn = _setUpFn;
        _setUpFn = () { parentFn(); setUpFn(); };
      } else {
        _setUpFn = setUpFn;
      }
    });
  }
}

/// Ensures that the global configuration for `scheduled_test` has been
/// initialized.
void _ensureInitialized() {
  unittest.ensureInitialized();
  unittest.wrapAsync = (f, [description]) {
    if (currentSchedule == null) {
      throw new StateError("Unexpected call to wrapAsync with no current "
          "schedule.");
    }

    return currentSchedule.wrapAsync(f, description);
  };
}

/// Like [wrapAsync], this ensures that the current task queue waits for
/// out-of-band asynchronous code, and that errors raised in that code are
/// handled correctly. However, [wrapFuture] wraps a [Future] chain rather than
/// a single callback.
///
/// The returned [Future] completes to the same value or error as [future].
///
/// [description] provides an optional description of the future, which is
/// used when generating error messages.
Future wrapFuture(Future future, [String description]) {
  if (currentSchedule == null) {
    throw new StateError("Unexpected call to wrapFuture with no current "
        "schedule.");
  }

  return currentSchedule.wrapFuture(future, description);
}

// TODO(nweiz): re-export these once issue 9535 is fixed.
unittest.Configuration get unittestConfiguration =>
  unittest.unittestConfiguration;
void set unittestConfiguration(unittest.Configuration value) {
  unittest.unittestConfiguration = value;
}
