// Copyright (c) 2017, 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=--enable-isolate-groups --experimental-enable-isolate-groups-jit
// VMOptions=--no-enable-isolate-groups

import "dart:async";
import "dart:io";
import "dart:isolate";
import "dart:math";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

const String loopbackIPv4String = "127.0.0.1";

void testArguments() {
  Expect.throws(() => RawSynchronousSocket.connectSync(null, 0));
  Expect
      .throws(() => RawSynchronousSocket.connectSync(loopbackIPv4String, null));
  Expect.throws(
      () => RawSynchronousSocket.connectSync(loopbackIPv4String, 65536));
  Expect.throws(() => RawSynchronousSocket.connectSync(loopbackIPv4String, -1));
}

// The connection attempt happens on the main Dart thread and the OS timeout can
// be arbitrarily long, causing timeout issues on the build bots. This isn't an
// issue with the async sockets since the lookup for a connect call happens on
// the IO service thread.
/*
void testInvalidConnect() {
  // Connect to an unknown DNS name.
  try {
    var socket = RawSynchronousSocket.connectSync("ko.faar.__hest__", 0);
    Expect.fail("Failure expected");
  } catch (e) {
    Expect.isTrue(e is SocketException);
  }

  // Connect to an unavaliable IP-address.
  try {
    var socket = RawSynchronousSocket.connectSync("1.2.3.4", 0);
    Expect.fail("Failure expected");
  } catch (e) {
    Expect.isTrue(e is SocketException);
  }
}
*/

void testSimpleConnect() {
  asyncStart();
  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
    var socket =
        RawSynchronousSocket.connectSync(loopbackIPv4String, server.port);
    server.listen((serverSocket) {
      Expect.equals(socket.address, serverSocket.remoteAddress);
      Expect.equals(socket.port, serverSocket.remotePort);
      Expect.equals(socket.remoteAddress, server.address);
      Expect.equals(socket.remotePort, server.port);
      socket.closeSync();
      server.close();
      asyncEnd();
    });
  });
}

void testServerListenAfterConnect() {
  asyncStart();
  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
    Expect.isTrue(server.port > 0);
    var client =
        RawSynchronousSocket.connectSync(loopbackIPv4String, server.port);
    server.listen((socket) {
      client.closeSync();
      server.close();
      socket.close();
      asyncEnd();
    });
  });
}

const messageSize = 1000;
// Configuration fields for the EchoServer.
enum EchoServerTypes {
  // Max accumulated connections to server before close. Defaults to 1.
  CONNECTION_COUNT,
  // Sets the range of the fields to check in the list generated by
  // createTestData().
  OFFSET_END,
  OFFSET_START,
  // The port used to communicate with an isolate.
  ISOLATE_SEND_PORT,
  // The port of the newly created echo server.
  SERVER_PORT
}

List<int> createTestData() {
  return new List<int>.generate(messageSize, (index) => index & 0xff);
}

// Consumes data generated by a test and compares it against the original test
// data. The optional fields, start and end, are used to compare against
// segments of the original test data list. In other words, data.length == (end
// - start).
void verifyTestData(List<int> data, [int start = 0, int end]) {
  assert(data != null);
  List<int> expected = createTestData();
  if (end == null) {
    end = data.length;
  }
  end = min(messageSize, end);
  Expect.equals(end - start, data.length);
  for (int i = 0; i < (end - start); i++) {
    Expect.equals(expected[start + i], data[i]);
  }
}

// The echo server is spawned in a new isolate and is used to test various
// synchronous read/write operations by echoing any data received back to the
// sender. The server should shutdown automatically after a specified number of
// socket disconnections (default: 1).
Future echoServer(var sendPort) async {
  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) async {
    ReceivePort receivePort = new ReceivePort();
    Map response = {
      EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort,
      EchoServerTypes.SERVER_PORT: server.port
    };
    sendPort.send(response);
    Map limits = await receivePort.first;
    int start = limits[EchoServerTypes.OFFSET_START];
    int end = limits[EchoServerTypes.OFFSET_END];
    int length = end - start;
    int connection_count = limits[EchoServerTypes.CONNECTION_COUNT] ?? 1;
    int connections = 0;
    sendPort = limits[EchoServerTypes.ISOLATE_SEND_PORT];
    server.listen((client) {
      int bytesRead = 0;
      int bytesWritten = 0;
      bool closedEventReceived = false;
      List<int> data = new List<int>(length);
      client.writeEventsEnabled = false;
      client.listen((event) {
        switch (event) {
          case RawSocketEvent.read:
            Expect.isTrue(bytesWritten == 0);
            Expect.isTrue(client.available() > 0);
            var buffer = client.read(client.available());
            data.setRange(bytesRead, bytesRead + buffer.length, buffer);
            bytesRead += buffer.length;
            // Once we've read all the data, we can echo it back. Otherwise,
            // keep waiting for more bytes.
            if (bytesRead >= length) {
              verifyTestData(data, start, end);
              client.writeEventsEnabled = true;
            }
            break;
          case RawSocketEvent.write:
            Expect.isFalse(client.writeEventsEnabled);
            bytesWritten +=
                client.write(data, bytesWritten, data.length - bytesWritten);
            if (bytesWritten < length) {
              client.writeEventsEnabled = true;
            } else if (bytesWritten == length) {
              // Close the socket for writing from the server since we're done
              // writing to this socket. The connection is closed completely
              // after the client closes the socket for reading from the server.
              client.shutdown(SocketDirection.send);
            }
            break;
          case RawSocketEvent.readClosed:
            client.close();
            break;
          case RawSocketEvent.closed:
            Expect.isFalse(closedEventReceived);
            closedEventReceived = true;
            break;
          default:
            throw "Unexpected event $event";
        }
      }, onDone: () {
        Expect.isTrue(closedEventReceived);
        connections++;
        if (connections >= connection_count) {
          server.close();
        }
      });
    }, onDone: () {
      // Let the client know we're shutting down then kill the isolate.
      sendPort.send(null);
      Isolate.current.kill();
    });
  });
}

Future testSimpleReadWrite({bool dropReads}) async {
  asyncStart();
  // This test creates a server and a client connects. The client writes data
  // to the socket and the server echos it back. The client confirms the data it
  // reads is the same as the data sent, then closes the socket, resulting in
  // the closing of the server, which responds on receivePort with null to
  // specify the echo server isolate is about to be killed. If an error occurs
  // in the echo server, the exception and stack trace are sent to receivePort,
  // which prints the exception and stack trace before eventually throwing an
  // error.
  ReceivePort receivePort = new ReceivePort();
  Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);

  Map response = await receivePort.first;
  SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
  int serverInternetPort = response[EchoServerTypes.SERVER_PORT];

  receivePort = new ReceivePort();
  echo.addErrorListener(receivePort.sendPort);

  Map limits = {
    EchoServerTypes.OFFSET_START: 0,
    EchoServerTypes.OFFSET_END: messageSize,
    EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
  };
  sendPort.send(limits);

  try {
    var socket = RawSynchronousSocket.connectSync(
        loopbackIPv4String, serverInternetPort);
    List<int> data = createTestData();
    socket.writeFromSync(data);
    List<int> result = socket.readSync(data.length);
    verifyTestData(result);
    socket.shutdown(SocketDirection.send);
    socket.closeSync();
  } catch (e, stack) {
    print("Echo test failed in the client");
    rethrow;
  }
  // Wait for the server to shutdown before finishing the test.
  var result = await receivePort.first;
  if (result != null) {
    throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
        " ${result[1]}";
  }
  asyncEnd();
}

Future testPartialRead() async {
  asyncStart();
  // This test is based on testSimpleReadWrite, but instead of reading the
  // entire echoed message at once, it reads it in two calls to readIntoSync.
  ReceivePort receivePort = new ReceivePort();
  Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);

  Map response = await receivePort.first;
  SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
  int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
  List<int> data = createTestData();

  receivePort = new ReceivePort();
  echo.addErrorListener(receivePort.sendPort);

  Map limits = {
    EchoServerTypes.OFFSET_START: 0,
    EchoServerTypes.OFFSET_END: 1000,
    EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
  };
  sendPort.send(limits);

  try {
    var socket = RawSynchronousSocket.connectSync(
        loopbackIPv4String, serverInternetPort);
    int half_length = (data.length / 2).toInt();

    // Send the full data list to the server.
    socket.writeFromSync(data);
    List<int> result = new List<int>(data.length);

    // Read half at a time and check that there's still more bytes available.
    socket.readIntoSync(result, 0, half_length);
    verifyTestData(result.sublist(0, half_length), 0, half_length);
    Expect.isTrue(socket.available() == (data.length - half_length));

    // Read the second half and verify again.
    socket.readIntoSync(result, half_length);
    verifyTestData(result);
    Expect.isTrue(socket.available() == 0);

    socket.closeSync();
  } catch (e, stack) {
    print("Echo test failed in the client.");
    rethrow;
  }
  // Wait for the server to shutdown before finishing the test.
  var result = await receivePort.first;
  if (result != null) {
    throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
        " ${result[1]}";
  }
  asyncEnd();
}

Future testPartialWrite() async {
  asyncStart();
  // This test is based on testSimpleReadWrite, but instead of writing the
  // entire data buffer at once, it writes different parts of the buffer over
  // multiple calls to writeFromSync.
  ReceivePort receivePort = new ReceivePort();
  Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);

  Map response = await receivePort.first;
  List<int> data = createTestData();
  SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
  int startOffset = 32;
  int endOffset = (data.length / 2).toInt();
  int serverInternetPort = response[EchoServerTypes.SERVER_PORT];

  receivePort = new ReceivePort();
  echo.addErrorListener(receivePort.sendPort);

  Map limits = {
    EchoServerTypes.OFFSET_START: startOffset,
    EchoServerTypes.OFFSET_END: endOffset,
    EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort
  };
  sendPort.send(limits);
  try {
    var socket = RawSynchronousSocket.connectSync(
        loopbackIPv4String, serverInternetPort);
    List<int> data = createTestData();

    // Write a subset of data to the server.
    socket.writeFromSync(data, startOffset, endOffset);

    // Grab the response and verify it's correct.
    List<int> result = new List<int>(endOffset - startOffset);
    socket.readIntoSync(result);

    Expect.equals(result.length, endOffset - startOffset);
    verifyTestData(result, startOffset, endOffset);
    socket.closeSync();
  } catch (e, stack) {
    print("Echo test failed in the client.");
    rethrow;
  }

  // Wait for the server to shutdown before finishing the test.
  var result = await receivePort.first;
  if (result != null) {
    throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
        " ${result[1]}";
  }
  asyncEnd();
}

Future testShutdown() async {
  asyncStart();
  // This test creates a server and a client connects. The client then tries to
  // perform various operations after being shutdown in a specific direction, to
  // ensure reads or writes cannot be performed if the socket has been shutdown
  // for reading or writing.
  ReceivePort receivePort = new ReceivePort();
  Isolate echo = await Isolate.spawn(echoServer, receivePort.sendPort);

  Map response = await receivePort.first;
  SendPort sendPort = response[EchoServerTypes.ISOLATE_SEND_PORT];
  int serverInternetPort = response[EchoServerTypes.SERVER_PORT];
  List<int> data = createTestData();

  receivePort = new ReceivePort();
  echo.addErrorListener(receivePort.sendPort);

  Map limits = {
    EchoServerTypes.OFFSET_START: 0,
    EchoServerTypes.OFFSET_END: data.length,
    EchoServerTypes.ISOLATE_SEND_PORT: receivePort.sendPort,
    // Tell the server to shutdown after 3 sockets disconnect.
    EchoServerTypes.CONNECTION_COUNT: 3
  };
  sendPort.send(limits);

  try {
    var socket = RawSynchronousSocket.connectSync(
        loopbackIPv4String, serverInternetPort);

    // Close from both directions. Shouldn't be able to read/write to the
    // socket.
    socket.shutdown(SocketDirection.both);
    Expect.throws(
        () => socket.writeFromSync(data), (e) => e is SocketException);
    Expect.throws(
        () => socket.readSync(data.length), (e) => e is SocketException);
    socket.closeSync();

    // Close the socket for reading then try and perform a read. This should
    // cause a SocketException.
    socket = RawSynchronousSocket.connectSync(
        loopbackIPv4String, serverInternetPort);
    socket.shutdown(SocketDirection.receive);
    // Throws exception when the socket is closed for RECEIVE.
    Expect.throws(
        () => socket.readSync(data.length), (e) => e is SocketException);
    socket.closeSync();

    // Close the socket for writing and try to do a write. This should cause an
    // OSError to be throw as the pipe is closed for writing.
    socket = RawSynchronousSocket.connectSync(
        loopbackIPv4String, serverInternetPort);
    socket.shutdown(SocketDirection.send);
    Expect.throws(
        () => socket.writeFromSync(data), (e) => e is SocketException);
    socket.closeSync();
  } catch (e, stack) {
    print("Echo test failed in client.");
    rethrow;
  }
  // Wait for the server to shutdown before finishing the test.
  var result = await receivePort.first;
  if (result != null) {
    throw "Echo test failed in server!\nError: ${result[0]}\nStack trace:" +
        " ${result[1]}";
  }
  asyncEnd();
}

Future testInvalidReadWriteOperations() {
  asyncStart();
  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
    server.listen((socket) {});
    List<int> data = createTestData();
    var socket =
        RawSynchronousSocket.connectSync(loopbackIPv4String, server.port);

    // Invalid writeFromSync invocations
    Expect.throwsRangeError(() => socket.writeFromSync(data, data.length + 1));
    Expect
        .throwsRangeError(() => socket.writeFromSync(data, 0, data.length + 1));
    Expect.throwsRangeError(() => socket.writeFromSync(data, 1, 0));
    Expect.throwsArgumentError(() => socket.writeFromSync(data, null));

    // Invalid readIntoSync invocations
    List<int> buffer = new List<int>(10);
    Expect
        .throwsRangeError(() => socket.readIntoSync(buffer, buffer.length + 1));
    Expect.throwsRangeError(
        () => socket.readIntoSync(buffer, 0, buffer.length + 1));
    Expect.throwsRangeError(() => socket.readIntoSync(buffer, 1, 0));
    Expect.throwsArgumentError(() => socket.readIntoSync(buffer, null));

    // Invalid readSync invocation
    Expect.throwsArgumentError(() => socket.readSync(-1));

    server.close();
    socket.closeSync();
    asyncEnd();
  });
}

void testClosedError() {
  asyncStart();
  RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
    server.listen((socket) {
      socket.close();
    });
    var socket =
        RawSynchronousSocket.connectSync(loopbackIPv4String, server.port);
    server.close();
    socket.closeSync();
    Expect.throws(() => socket.remotePort, (e) => e is SocketException);
    Expect.throws(() => socket.remoteAddress, (e) => e is SocketException);
    asyncEnd();
  });
}

main() async {
  asyncStart();
  testArguments();
  // testInvalidConnect(); Long timeout for bad lookups, so disable for bots.
  await testShutdown();
  testSimpleConnect();
  testServerListenAfterConnect();
  await testSimpleReadWrite();
  await testPartialRead();
  await testPartialWrite();
  testInvalidReadWriteOperations();
  testClosedError();
  asyncEnd();
}
