// 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 error_group_test;

import 'dart:async';

import 'package:unittest/unittest.dart';

import '../lib/src/error_group.dart';
import '../lib/src/utils.dart';

ErrorGroup errorGroup;

// TODO(nweiz): once there's a global error handler, we should test that it does
// and does not get called at appropriate times. See issue 5958.
//
// One particular thing we should test that has no tests now is that a stream
// that has a subscription added and subsequently canceled counts as having no
// listeners.

main() {
  group('with no futures or streams', () {
    setUp(() {
      errorGroup = new ErrorGroup();
    });

    test('should pass signaled errors to .done', () {
      expect(errorGroup.done, throwsFormatException);
      errorGroup.signalError(new FormatException());
    });

    test("shouldn't allow additional futures or streams once an error has been "
        "signaled", () {
      expect(errorGroup.done, throwsFormatException);
      errorGroup.signalError(new FormatException());

      expect(() => errorGroup.registerFuture(new Future.value()),
          throwsStateError);
      expect(() => errorGroup.registerStream(
          new StreamController(sync: true).stream),
          throwsStateError);
    });
  });

  group('with a single future', () {
    Completer completer;
    Future future;

    setUp(() {
      errorGroup = new ErrorGroup();
      completer = new Completer();
      future = errorGroup.registerFuture(completer.future);
    });

    test('should pass through a value from the future', () {
      expect(future, completion(equals('value')));
      expect(errorGroup.done, completes);
      completer.complete('value');
    });

    test("shouldn't allow additional futures or streams once .done has "
        "been called", () {
      completer.complete('value');

      expect(completer.future
                 .then((_) => errorGroup.registerFuture(new Future.value())),
             throwsStateError);
      expect(completer.future
                 .then((_) => errorGroup.registerStream(
                     new StreamController(sync: true).stream)),
            throwsStateError);
    });

    test('should pass through an exception from the future if it has a '
        'listener', () {
      expect(future, throwsFormatException);
      // errorGroup shouldn't top-level the exception
      completer.completeError(new FormatException());
    });

    test('should notify the error group of an exception from the future even '
        'if it has a listener', () {
      expect(future, throwsFormatException);
      expect(errorGroup.done, throwsFormatException);
      completer.completeError(new FormatException());
    });

    test('should pass a signaled exception to the future if it has a listener '
        'and should ignore a subsequent value from that future', () {
      expect(future, throwsFormatException);
      // errorGroup shouldn't top-level the exception
      errorGroup.signalError(new FormatException());
      completer.complete('value');
    });

    test('should pass a signaled exception to the future if it has a listener '
        'and should ignore a subsequent exception from that future', () {
      expect(future, throwsFormatException);
      // errorGroup shouldn't top-level the exception
      errorGroup.signalError(new FormatException());
      completer.completeError(new ArgumentError());
    });

    test('should notify the error group of a signaled exception even if the '
        'future has a listener', () {
      expect(future, throwsFormatException);
      expect(errorGroup.done, throwsFormatException);
      errorGroup.signalError(new FormatException());
    });

    test("should complete .done if the future receives a value even if the "
        "future doesn't have a listener", () {
      expect(errorGroup.done, completes);
      completer.complete('value');

      // A listener added afterwards should receive the value
      expect(errorGroup.done.then((_) => future),
          completion(equals('value')));
    });

    test("should pipe an exception from the future to .done if the future "
        "doesn't have a listener", () {
      expect(errorGroup.done, throwsFormatException);
      completer.completeError(new FormatException());

      // A listener added afterwards should receive the exception
      expect(errorGroup.done.catchError((_) {
        expect(future, throwsFormatException);
      }), completes);
    });

    test("should pass a signaled exception to .done if the future doesn't have "
        "a listener",
        () {
      expect(errorGroup.done, throwsFormatException);
      errorGroup.signalError(new FormatException());

      // A listener added afterwards should receive the exception
      expect(errorGroup.done.catchError((_) {
        completer.complete('value'); // should be ignored
        expect(future, throwsFormatException);
      }), completes);
    });
  });

  group('with multiple futures', () {
    Completer completer1;
    Completer completer2;
    Future future1;
    Future future2;

    setUp(() {
      errorGroup = new ErrorGroup();
      completer1 = new Completer();
      completer2 = new Completer();
      future1 = errorGroup.registerFuture(completer1.future);
      future2 = errorGroup.registerFuture(completer2.future);
    });

    test("should pipe exceptions from one future to the other and to "
        ".complete", () {
      expect(future1, throwsFormatException);
      expect(future2, throwsFormatException);
      expect(errorGroup.done, throwsFormatException);

      completer1.completeError(new FormatException());
    });

    test("each future should be able to complete with a value "
        "independently", () {
      expect(future1, completion(equals('value1')));
      expect(future2, completion(equals('value2')));
      expect(errorGroup.done, completes);

      completer1.complete('value1');
      completer2.complete('value2');
    });

    test("shouldn't throw a top-level exception if a future receives an error "
        "after the other listened future completes", () {
      expect(future1, completion(equals('value')));
      completer1.complete('value');

      expect(future1.then((_) {
        // shouldn't cause a top-level exception
        completer2.completeError(new FormatException());
      }), completes);
    });

    test("shouldn't throw a top-level exception if an error is signaled after "
        "one listened future completes", () {
      expect(future1, completion(equals('value')));
      completer1.complete('value');

      expect(future1.then((_) {
        // shouldn't cause a top-level exception
        errorGroup.signalError(new FormatException());
      }), completes);
    });
  });

  group('with a single stream', () {
    StreamController controller;
    Stream stream;

    setUp(() {
      errorGroup = new ErrorGroup();
      controller = new StreamController(sync: true);
      stream = errorGroup.registerStream(controller.stream.asBroadcastStream());
    });

    test('should pass through values from the stream', () {
      StreamIterator iter = new StreamIterator(stream);
      iter.moveNext().then((hasNext) {
        expect(hasNext, isTrue);
        expect(iter.current, equals(1));
        iter.moveNext().then((hasNext) {
          expect(hasNext, isTrue);
          expect(iter.current, equals(2));
          expect(iter.moveNext(), completion(isFalse));
        });
      });
      expect(errorGroup.done, completes);

      controller..add(1)..add(2)..close();
    });

    test('should pass through an error from the stream if it has a '
        'listener', () {
      expect(stream.first, throwsFormatException);
      // errorGroup shouldn't top-level the exception
      controller.addError(new FormatException());
    });

    test('should notify the error group of an exception from the stream even '
        'if it has a listener', () {
      expect(stream.first, throwsFormatException);
      expect(errorGroup.done, throwsFormatException);
      controller.addError(new FormatException());
    });

    test('should pass a signaled exception to the stream if it has a listener '
         'and should unsubscribe that stream', () {
      // errorGroup shouldn't top-level the exception
      expect(stream.first, throwsFormatException);
      errorGroup.signalError(new FormatException());

      expect(new Future(() {
        controller.add('value');
      }), completes);
    });

    test('should notify the error group of a signaled exception even if the '
        'stream has a listener', () {
      expect(stream.first, throwsFormatException);
      expect(errorGroup.done, throwsFormatException);
      errorGroup.signalError(new FormatException());
    });

    test("should see one value and complete .done when the stream is done even "
         "if the stream doesn't have a listener", () {
      expect(errorGroup.done, completes);
      controller.add('value');
      controller.close();

      // Now that broadcast controllers have been removed a listener should
      // see the value that has been put into the controller.
      expect(errorGroup.done.then((_) => stream.toList()),
          completion(equals(['value'])));
    });

  });

  group('with a single single-subscription stream', () {
    StreamController controller;
    Stream stream;

    setUp(() {
      errorGroup = new ErrorGroup();
      controller = new StreamController(sync: true);
      stream = errorGroup.registerStream(controller.stream);
    });

    test("should complete .done when the stream is done even if the stream "
        "doesn't have a listener", () {
      expect(errorGroup.done, completes);
      controller.add('value');
      controller.close();

      // A listener added afterwards should receive the value
      expect(errorGroup.done.then((_) => stream.toList()),
          completion(equals(['value'])));
    });

    test("should pipe an exception from the stream to .done if the stream "
        "doesn't have a listener", () {
      expect(errorGroup.done, throwsFormatException);
      controller.addError(new FormatException());

      // A listener added afterwards should receive the exception
      expect(errorGroup.done.catchError((_) {
        controller.add('value'); // should be ignored
        expect(stream.first, throwsFormatException);
      }), completes);
    });

    test("should pass a signaled exception to .done if the stream doesn't "
        "have a listener",
        () {
      expect(errorGroup.done, throwsFormatException);
      errorGroup.signalError(new FormatException());

      // A listener added afterwards should receive the exception
      expect(errorGroup.done.catchError((_) {
        controller.add('value'); // should be ignored
        expect(stream.first, throwsFormatException);
      }), completes);
    });
  });

  group('with multiple streams', () {
    StreamController controller1;
    StreamController controller2;
    Stream stream1;
    Stream stream2;

    setUp(() {
      errorGroup = new ErrorGroup();
      controller1 = new StreamController(sync: true);
      controller2 = new StreamController(sync: true);
      stream1 = errorGroup.registerStream(controller1.stream.asBroadcastStream());
      stream2 = errorGroup.registerStream(controller2.stream.asBroadcastStream());
    });

    test("should pipe exceptions from one stream to the other and to .done",
        () {
      expect(stream1.first, throwsFormatException);
      expect(stream2.first, throwsFormatException);
      expect(errorGroup.done, throwsFormatException);

      controller1.addError(new FormatException());
    });

    test("each future should be able to emit values independently", () {
      expect(stream1.toList(), completion(equals(['value1.1', 'value1.2'])));
      expect(stream2.toList(), completion(equals(['value2.1', 'value2.2'])));
      expect(errorGroup.done, completes);

      controller1..add('value1.1')..add('value1.2')..close();
      controller2..add('value2.1')..add('value2.2')..close();
    });

    test("shouldn't throw a top-level exception if a stream receives an error "
        "after the other listened stream completes", () {
      var signal = new Completer();
      expect(stream1.toList().whenComplete(signal.complete),
             completion(equals(['value1', 'value2'])));
      controller1..add('value1')..add('value2')..close();

      expect(signal.future.then((_) {
        // shouldn't cause a top-level exception
        controller2.addError(new FormatException());
      }), completes);
    });

    test("shouldn't throw a top-level exception if an error is signaled after "
        "one listened stream completes", () {
      var signal = new Completer();
      expect(stream1.toList().whenComplete(signal.complete),
             completion(equals(['value1', 'value2'])));
      controller1..add('value1')..add('value2')..close();

      expect(signal.future.then((_) {
        // shouldn't cause a top-level exception
        errorGroup.signalError(new FormatException());
      }), completes);
    });
  });

  group('with a stream and a future', () {
    StreamController controller;
    Stream stream;
    Completer completer;
    Future future;

    setUp(() {
      errorGroup = new ErrorGroup();
      controller = new StreamController(sync: true);
      stream = errorGroup.registerStream(controller.stream.asBroadcastStream());
      completer = new Completer();
      future = errorGroup.registerFuture(completer.future);
    });

    test("should pipe exceptions from the stream to the future", () {
      expect(stream.first, throwsFormatException);
      expect(future, throwsFormatException);
      expect(errorGroup.done, throwsFormatException);

      controller.addError(new FormatException());
    });

    test("should pipe exceptions from the future to the stream", () {
      expect(stream.first, throwsFormatException);
      expect(future, throwsFormatException);
      expect(errorGroup.done, throwsFormatException);

      completer.completeError(new FormatException());
    });

    test("the stream and the future should be able to complete/emit values "
        "independently", () {
      expect(stream.toList(), completion(equals(['value1.1', 'value1.2'])));
      expect(future, completion(equals('value2.0')));
      expect(errorGroup.done, completes);

      controller..add('value1.1')..add('value1.2')..close();
      completer.complete('value2.0');
    });

    test("shouldn't throw a top-level exception if the stream receives an error "
        "after the listened future completes", () {
      expect(future, completion(equals('value')));
      completer.complete('value');

      expect(future.then((_) {
        // shouldn't cause a top-level exception
        controller.addError(new FormatException());
      }), completes);
    });

    test("shouldn't throw a top-level exception if the future receives an "
        "error after the listened stream completes", () {
      var signal = new Completer();
      expect(stream.toList().whenComplete(signal.complete),
             completion(equals(['value1', 'value2'])));
      controller..add('value1')..add('value2')..close();

      expect(signal.future.then((_) {
        // shouldn't cause a top-level exception
        completer.completeError(new FormatException());
      }), completes);
    });
  });
}
