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

// Test creating a large number of socket connections.
library ServerTest;

import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";
import "dart:async";
import "dart:io";
import "dart:isolate";
part "testing_server.dart";

const connectionsCount = 200;

class SocketManyConnectionsTest {
  SocketManyConnectionsTest.start()
      : _connections = 0,
        _sockets = new List<Socket>.filled(connectionsCount, null) {
    initialize();
  }

  void run() {
    void connectHandler() {
      _connections++;
      if (_connections == connectionsCount) {
        for (int i = 0; i < connectionsCount; i++) {
          _sockets[i].destroy();
        }
        close();
      }
    }

    for (int i = 0; i < connectionsCount; i++) {
      Socket.connect(TestingServer.HOST, _port).then((socket) {
        Expect.isNotNull(socket);
        _sockets[i] = socket;
        connectHandler();
      });
    }
  }

  void initialize() {
    var receivePort = new ReceivePort();
    var remote = Isolate.spawn(startTestServer, receivePort.sendPort);
    receivePort.first.then((msg) {
      this._port = msg[0];
      this._closeSendPort = msg[1];
      run();
    });
  }

  void close() {
    _closeSendPort.send(null);
    asyncEnd();
  }

  int _port;
  SendPort _closeSendPort;
  List<Socket> _sockets;
  int _connections;
}

void startTestServer(SendPort replyPort) {
  var server = new TestServer();
  server.init().then((port) {
    replyPort.send([port, server.closeSendPort]);
  });
}

class TestServer extends TestingServer {
  void onConnection(Socket connection) {
    Socket _client;

    void closeHandler() {
      connection.close();
    }

    void errorHandler(e, trace) {
      String msg = "Socket error $e";
      if (trace != null) msg += "\nStackTrace: $trace";
      print(msg);
      connection.close();
    }

    _connections++;
    connection.listen((data) {}, onDone: closeHandler, onError: errorHandler);
  }

  int _connections = 0;
}

main() {
  asyncStart();
  SocketManyConnectionsTest test = new SocketManyConnectionsTest.start();
}
