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

// @dart = 2.9

// VMOptions=--no-enable-fast-object-copy
// VMOptions=--enable-fast-object-copy

import "dart:io" show ServerSocket;
import "dart:isolate";
import "dart:typed_data" show ByteData;

import "package:expect/expect.dart";

void main() async {
  final port = new ReceivePort();

  // Sending a socket object will result in an error.
  final socket = await ServerSocket.bind('localhost', 0);

  final x = new ByteData(4);
  for (int i = 0; i < 4; i++) {
    x.setUint8(i, i);
  }
  {
    final transferableFirst = TransferableTypedData.fromList([x]);
    Expect.throwsArgumentError(
        () => port.sendPort.send(<dynamic>[transferableFirst, socket]));
    // Once TransferableTypedData was sent even if attempt failed, it can't be
    // materialized.
    // This need to be changed so that on failed send we should not detach the
    // buffer form the transferrable. The order should not matter (i.e. if the
    // error happens before or after the serializer hits a transferrable object)

    final data1 = transferableFirst.materialize().asUint8List();
    Expect.equals(x.lengthInBytes, data1.length);
    for (int i = 0; i < data1.length; i++) {
      Expect.equals(i, data1[i]);
    }
  }
  {
    final transferableFirst = TransferableTypedData.fromList([x]);
    Expect.throwsArgumentError(() => port.sendPort
        .send(<dynamic>[transferableFirst, transferableFirst, socket]));
    // Once TransferableTypedData was sent even if attempt failed, it can't be
    // materialized.
    // This need to be changed so that on failed send we should not detach the
    // buffer form the transferrable. The order should not matter (i.e. if the
    // error happens before or after the serializer hits a transferrable object)

    final data1 = transferableFirst.materialize().asUint8List();
    Expect.equals(x.lengthInBytes, data1.length);
    for (int i = 0; i < data1.length; i++) {
      Expect.equals(i, data1[i]);
    }
  }

  {
    final transferableSecond = TransferableTypedData.fromList([x]);
    Expect.throwsArgumentError(
        () => port.sendPort.send(<dynamic>[socket, transferableSecond]));
    // Once TransferableTypedData was sent even if attempt failed, it can't be
    // materialized.
    final data2 = transferableSecond.materialize().asUint8List();
    Expect.equals(x.lengthInBytes, data2.length);
    for (int i = 0; i < data2.length; i++) {
      Expect.equals(i, data2[i]);
    }
  }

  {
    final transferableSecond = TransferableTypedData.fromList([x]);
    Expect.throwsArgumentError(() => port.sendPort
        .send(<dynamic>[socket, transferableSecond, transferableSecond]));
    // Once TransferableTypedData was sent even if attempt failed, it can't be
    // materialized.
    final data2 = transferableSecond.materialize().asUint8List();
    Expect.equals(x.lengthInBytes, data2.length);
    for (int i = 0; i < data2.length; i++) {
      Expect.equals(i, data2[i]);
    }
  }

  socket.close();
  port.close();
}
