// 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.

// VMOptions=--enable-isolate-groups
// VMOptions=--no-enable-isolate-groups
//
// 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();
  }

  late int _port;
  late 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();
}
