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

/// @assertion void addOnExitListener(
///                    SendPort responsePort, {
///                    Object response
///            })
/// ...
///   Adding the same port more than once will only cause it to receive one
/// message, using the last response value that was added.
///
/// @description Check that isolate sends single event on responsePort,
/// which is supplied several times to addOnExitListener() of the same isolate.
/// Always the same value for parameter response is specified.
///
/// @author a.semenov@unipro.ru

import "dart:isolate";
import "dart:async";
import "../../../Utils/expect.dart";
import "IsolateUtil.dart";

Future test(Object? value) async {
  ErrorServer server = await ErrorServer.spawn(errorsAreFatal:false);
  ReceivePort onExit = new ReceivePort();
  List events = [];
  onExit.listen(
    (data) {
      events.add(data);
    }
  );
  server.isolate.addOnExitListener(onExit.sendPort, response:value);
  server.isolate.addOnExitListener(onExit.sendPort, response:value);
  server.isolate.addOnExitListener(onExit.sendPort, response:value);
  server.requestStop();
  await new Future.delayed(TWO_SECONDS); // wait for duplicate events
  onExit.close();
  Expect.listEquals([value], events);
}

main() {
  asyncStart();
  Future.wait([
    test(null),
    test(true),
    test(false),
    test("string"),
    test(10),
    test(1.1),
    test(double.nan),
    test(double.infinity)
  ]).then((_) => asyncEnd());
}
