// Copyright (c) 2018, 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.
//
// Validates functionality of Isolate.exit().

// @dart = 2.9

import 'dart:async';
import 'dart:isolate';
import 'dart:nativewrappers';

import "package:expect/expect.dart";

import "isolates/fast_object_copy_test.dart" show nonCopyableClosures;

import "isolates/fast_object_copy2_test.dart"
    show sharableObjects, copyableClosures;

doNothingWorker(data) {}

spawnWorker(worker, data) async {
  Completer completer = Completer();
  runZoned(() async {
    final isolate = await Isolate.spawn(worker, [data]);
    completer.complete(isolate);
  }, onError: (e, st) => completer.complete(e));
  return await completer.future;
}

class NativeWrapperClass extends NativeFieldWrapperClass1 {}

verifyCantSendNative() async {
  final receivePort = ReceivePort();
  Expect.throws(
      () => Isolate.exit(receivePort.sendPort, NativeWrapperClass()),
      (e) => e.toString().startsWith('Invalid argument: '
          '"Illegal argument in isolate message : '
          '(object extends NativeWrapper'));
  receivePort.close();
}

verifyCantSendReceivePort() async {
  final receivePort = ReceivePort();
  Expect.throws(
      () => Isolate.exit(receivePort.sendPort, receivePort),
      (e) => e.toString().startsWith(
          'Invalid argument: "Illegal argument in isolate message : '
          '(object is a ReceivePort)\"'));
  receivePort.close();
}

verifyCantSendNonCopyable() async {
  final port = ReceivePort();
  final inbox = StreamIterator<dynamic>(port);
  final isolate = await Isolate.spawn((sendPort) {
    for (final closure in nonCopyableClosures) {
      Expect.throwsArgumentError(() => Isolate.exit(sendPort, closure));
    }
    sendPort.send(true);
  }, port.sendPort);

  await inbox.moveNext();
  Expect.isTrue(inbox.current);
  port.close();
}

sendShareable(SendPort sendPort) {
  Isolate.exit(sendPort, sharableObjects);
}

verifyCanSendShareable() async {
  final port = ReceivePort();
  final inbox = StreamIterator<dynamic>(port);
  final isolate = await Isolate.spawn(sendShareable, port.sendPort);

  await inbox.moveNext();
  final result = inbox.current;
  Expect.equals(sharableObjects.length, result.length);
  port.close();
}

sendCopyable(SendPort sendPort) {
  Isolate.exit(sendPort, copyableClosures);
}

verifyCanSendCopyableClosures() async {
  final port = ReceivePort();
  final inbox = StreamIterator<dynamic>(port);
  final isolate = await Isolate.spawn(sendCopyable, port.sendPort);

  await inbox.moveNext();
  final result = inbox.current;
  Expect.equals(copyableClosures.length, result.length);
  port.close();
}

add(a, b) => a + b;

worker(SendPort sendPort) async {
  Isolate.exit(sendPort, add);
}

verifyExitMessageIsPostedLast() async {
  final port = ReceivePort();
  final inbox = new StreamIterator<dynamic>(port);
  final isolate =
      await Isolate.spawn(worker, port.sendPort, onExit: port.sendPort);

  final receivedData = Completer<dynamic>();
  final isolateExited = Completer<bool>();
  port.listen((dynamic resultData) {
    if (receivedData.isCompleted) {
      Expect.equals(
          null, resultData); // exit message comes after data is receivedData
      isolateExited.complete(true);
    } else {
      receivedData.complete(resultData);
    }
  });
  Expect.equals(true, await isolateExited.future);
  Expect.equals(5, (await receivedData.future)(2, 3));
  port.close();
}

main() async {
  await verifyCantSendNative();
  await verifyCantSendReceivePort();
  await verifyCantSendNonCopyable();
  await verifyCanSendShareable();
  await verifyCanSendCopyableClosures();
  await verifyExitMessageIsPostedLast();
}
