// 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 --experimental-enable-isolate-groups-jit
// 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();
}
