// 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.

library test_utils;

import 'dart:async';

import 'package:scheduled_test/scheduled_test.dart';
import 'package:scheduled_test/src/utils.dart';
import 'package:scheduled_test/src/mock_clock.dart' as mock_clock;

import 'metatest.dart';

export 'package:scheduled_test/src/utils.dart';

/// Wraps [input] to provide a timeout. If [input] completes before
/// [milliseconds] have passed, then the return value completes in the same way.
/// However, if [milliseconds] pass before [input] has completed, [onTimeout] is
/// run and its result is passed to [input] (with chaining, if it returns a
/// [Future]).
///
/// Note that timing out will not cancel the asynchronous operation behind
/// [input].
Future timeout(Future input, int milliseconds, onTimeout()) {
  var completer = new Completer();
  var timer = new Timer(new Duration(milliseconds: milliseconds), () {
    chainToCompleter(syncFuture(onTimeout), completer);
  });
  input.then((value) {
    if (completer.isCompleted) return;
    timer.cancel();
    completer.complete(value);
  }).catchError((error, stackTrace) {
    if (completer.isCompleted) return;
    timer.cancel();
    completer.completeError(error, stackTrace);
  });
  return completer.future;
}

/// Returns a [Future] that will complete in [milliseconds].
Future sleep(int milliseconds) {
  var completer = new Completer();
  mock_clock.newTimer(new Duration(milliseconds: milliseconds), () {
    completer.complete();
  });
  return completer.future;
}

/// Sets up a timeout for every metatest in this file.
void setUpTimeout() {
  metaSetUp(() {
    // TODO(nweiz): We used to only increase the timeout to 10s for the Windows
    // bots, but the Linux and Mac bots have started taking upwards of 5s when
    // running pumpEventQueue, so we're increasing the timeout across the board
    // (see issue 9248).
    currentSchedule.timeout = new Duration(seconds: 10);
  });
}

/// Creates a metatest with [body] and asserts that it passes.
///
/// This is like [expectTestsPass], but the [test] is set up automatically.
void expectTestPasses(String description, Future body()) =>
  expectTestsPass(description, () => test('test', body));

/// Creates a metatest that runs [testBody], captures its schedule errors, and
/// passes them to [validator].
///
/// [testBody] is expected to produce an error, while [validator] is expected to
/// produce none.
void expectTestFails(String description, Future testBody(),
    void validator(List<ScheduleError> errors)) {
  expectTestsPass(description, () {
    var errors;
    test('test body', () {
      currentSchedule.onException.schedule(() {
        errors = currentSchedule.errors;
      });

      testBody();
    });

    test('validate errors', () {
      expect(errors, everyElement(new isInstanceOf<ScheduleError>()));
      validator(errors);
    });
  }, passing: ['validate errors']);
}
