// 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.
//
// VMOptions=
// VMOptions=--short_socket_read
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write

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

const SERVER_ADDRESS = "127.0.0.1";
const HOST_NAME = "localhost";
const CERTIFICATE = "localhost_cert";

void testArguments() {
  Expect.throws(() =>
      SecureServerSocket.bind(SERVER_ADDRESS, 65536, 5, CERTIFICATE));
  Expect.throws(() =>
      SecureServerSocket.bind(SERVER_ADDRESS, -1, CERTIFICATE));
  Expect.throws(() =>
      SecureServerSocket.bind(SERVER_ADDRESS, 0, -1, CERTIFICATE));
}

void testSimpleBind() {
  ReceivePort port = new ReceivePort();
  SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((s) {
    Expect.isTrue(s.port > 0);
    s.close();
    port.close();
  });
}

void testInvalidBind() {
  int count = 0;
  ReceivePort port = new ReceivePort();
  port.receive((_, __) { count++; if (count == 3) port.close(); });

  // Bind to a unknown DNS name.
  SecureServerSocket.bind("ko.faar.__hest__", 0, 5, CERTIFICATE).then((_) {
    Expect.fail("Failure expected");
  }).catchError((e) {
    Expect.isTrue(e.error is SocketIOException);
    port.toSendPort().send(1);
  });

  // Bind to an unavaliable IP-address.
  SecureServerSocket.bind("8.8.8.8", 0, 5, CERTIFICATE).then((_) {
    Expect.fail("Failure expected");
  }).catchError((e) {
    Expect.isTrue(e.error is SocketIOException);
    port.toSendPort().send(1);
  });

  // Bind to a port already in use.
  // Either an error or a successful bind is allowed.
  // Windows platforms allow multiple binding to the same socket, with
  // unpredictable results.
  SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((s) {
    SecureServerSocket.bind(SERVER_ADDRESS,
                            s.port,
                            5,
                            CERTIFICATE).then((t) {
      Expect.equals('windows', Platform.operatingSystem);
      Expect.equals(s.port, t.port);
      s.close();
      t.close();
      port.toSendPort().send(1);
    }).catchError((e) {
      Expect.notEquals('windows', Platform.operatingSystem);
      Expect.isTrue(e.error is SocketIOException);
      s.close();
      port.toSendPort().send(1);
    });
  });
}

void testSimpleConnect(String certificate) {
  ReceivePort port = new ReceivePort();
  SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, certificate).then((server) {
    var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port);
    server.listen((serverEnd) {
      clientEndFuture.then((clientEnd) {
        clientEnd.close();
        serverEnd.close();
        server.close();
        port.close();
      });
    });
  });
}

void testSimpleConnectFail(String certificate) {
  ReceivePort port = new ReceivePort();
  SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, certificate).then((server) {
    var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port)
      .then((clientEnd) {
        Expect.fail("No client connection expected.");
      })
      .catchError((e) {
        Expect.isTrue(e is AsyncError);
        Expect.isTrue(e.error is SocketIOException);
      });
    server.listen((serverEnd) {
      Expect.fail("No server connection expected.");
    },
    onError: (e) {
      Expect.isTrue(e is AsyncError);
      Expect.isTrue(e.error is SocketIOException);
      clientEndFuture.then((_) => port.close());
    });
  });
}

void testServerListenAfterConnect() {
  ReceivePort port = new ReceivePort();
  SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
    Expect.isTrue(server.port > 0);
    var clientEndFuture = SecureSocket.connect(HOST_NAME, server.port);
    new Timer(500, (_) {
      server.listen((serverEnd) {
        clientEndFuture.then((clientEnd) {
          clientEnd.close();
          serverEnd.close();
          server.close();
          port.close();
        });
      });
    });
  });
}

void testSimpleReadWrite() {
  // This test creates a server and a client connects. The client then
  // writes and the server echos. When the server has finished its
  // echo it half-closes. When the client gets the close event is
  // closes fully.
  ReceivePort port = new ReceivePort();

  const messageSize = 1000;

  List<int> createTestData() {
    List<int> data = new List.fixedLength(messageSize);
    for (int i = 0; i < messageSize; i++) {
      data[i] = i & 0xff;
    }
    return data;
  }

  void verifyTestData(List<int> data) {
    Expect.equals(messageSize, data.length);
    List<int> expected = createTestData();
    for (int i = 0; i < messageSize; i++) {
      Expect.equals(expected[i], data[i]);
    }
  }

  SecureServerSocket.bind(SERVER_ADDRESS, 0, 5, CERTIFICATE).then((server) {
    server.listen((client) {
      int bytesRead = 0;
      int bytesWritten = 0;
      List<int> data = new List.fixedLength(messageSize);

      client.listen(
        (buffer) {
          Expect.isTrue(bytesWritten == 0);
          data.setRange(bytesRead, buffer.length, buffer);
          bytesRead += buffer.length;
          if (bytesRead == data.length) {
            verifyTestData(data);
            client.add(data);
            client.close();
          }
        },
        onDone: () {
          server.close();
        });
    });

    SecureSocket.connect(HOST_NAME, server.port).then((socket) {
      int bytesRead = 0;
      int bytesWritten = 0;
      List<int> dataSent = createTestData();
      List<int> dataReceived = new List<int>.fixedLength(dataSent.length);
      socket.add(dataSent);
      socket.close();  // Can also be delayed.
      socket.listen(
        (List<int> buffer) {
          dataReceived.setRange(bytesRead, buffer.length, buffer);
          bytesRead += buffer.length;
        },
        onDone: () {
          verifyTestData(dataReceived);
          socket.close();
          port.close();
        });
    });
  });
}

main() {
  Path scriptDir = new Path(new Options().script).directoryPath;
  Path certificateDatabase = scriptDir.append('pkcert');
  SecureSocket.initialize(database: certificateDatabase.toNativePath(),
                          password: 'dartdart',
                          useBuiltinRoots: false);
  testArguments();
  testSimpleBind();
  testInvalidBind();
  testSimpleConnect(CERTIFICATE);
  testSimpleConnect("CN=localhost");
  testSimpleConnectFail("not_a_nickname");
  testSimpleConnectFail("CN=notARealDistinguishedName");
  testServerListenAfterConnect();
  testSimpleReadWrite();
}
