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

// @dart = 2.9

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

Future sendData(List<int> data, int port) {
  return Socket.connect("127.0.0.1", port).then((socket) {
    socket.listen((data) {
      Expect.fail("No data response was expected");
    });
    socket.add(data);
    return socket.close().then((_) {
      socket.destroy();
    });
  });
}

class EarlyCloseTest {
  EarlyCloseTest(this.data,
      [String this.exception, bool this.expectRequest = false]);

  Future execute() {
    return HttpServer.bind("127.0.0.1", 0).then((server) {
      Completer c = new Completer();

      bool calledOnRequest = false;
      bool calledOnError = false;
      bool calledOnDone = false;
      ReceivePort port = new ReceivePort();
      var requestCompleter = new Completer();
      server.listen((request) {
        Expect.isTrue(expectRequest);
        Expect.isFalse(calledOnError);
        Expect.isFalse(calledOnRequest, "onRequest called multiple times");
        calledOnRequest = true;
        request.listen((_) {}, onDone: () {
          requestCompleter.complete();
        }, onError: (error) {
          Expect.isFalse(calledOnError);
          Expect.equals(exception, error.message);
          calledOnError = true;
          if (exception != null) port.close();
        });
      }, onDone: () {
        Expect.equals(expectRequest, calledOnRequest);
        calledOnDone = true;
        if (exception == null) port.close();
        c.complete(null);
      });

      List<int> d;
      if (data is List<int>) d = data;
      if (data is String) d = data.codeUnits;
      if (d == null) Expect.fail("Invalid data");
      sendData(d, server.port).then((_) {
        if (!expectRequest) requestCompleter.complete();
        requestCompleter.future.then((_) => server.close());
      });

      return c.future;
    });
  }

  final data;
  final String exception;
  final bool expectRequest;
}

void testEarlyClose1() {
  List<EarlyCloseTest> tests = new List<EarlyCloseTest>();
  void add(Object data, [String exception, bool expectRequest = false]) {
    tests.add(new EarlyCloseTest(data, exception, expectRequest));
  }
  // The empty packet is valid.

  // Close while sending header
  add("G");
  add("GET /");
  add("GET / HTTP/1.1");
  add("GET / HTTP/1.1\r\n");

  // Close while sending content
  add("GET / HTTP/1.1\r\nContent-Length: 100\r\n\r\n",
      "Connection closed while receiving data", true);
  add("GET / HTTP/1.1\r\nContent-Length: 100\r\n\r\n1",
      "Connection closed while receiving data", true);

  void runTest(Iterator it) {
    if (it.moveNext()) {
      it.current.execute().then((_) {
        runTest(it);
      });
    }
  }

  runTest(tests.iterator);
}

testEarlyClose2() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((request) {
      String name = Platform.script.toFilePath();
      new File(name)
          .openRead()
          .cast<List<int>>()
          .pipe(request.response)
          .catchError((e) {/* ignore */});
    });

    var count = 0;
    makeRequest() {
      Socket.connect("127.0.0.1", server.port).then((socket) {
        var data = "GET / HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
        socket.write(data);
        socket.close();
        socket.done.then((_) {
          socket.destroy();
          if (++count < 10) {
            makeRequest();
          } else {
            scheduleMicrotask(server.close);
          }
        });
      });
    }

    makeRequest();
  });
}

void testEarlyClose3() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((request) {
      var subscription;
      subscription = request.listen((_) {}, onError: (error) {
        // subscription.cancel should not trigger an error.
        subscription.cancel();
        server.close();
      });
    });
    Socket.connect("127.0.0.1", server.port).then((socket) {
      socket.write("GET / HTTP/1.1\r\n");
      socket.write("Content-Length: 10\r\n");
      socket.write("\r\n");
      socket.write("data");
      socket.close();
      socket.listen((_) {}, onError: (_) {});
      socket.done.catchError((_) {});
    });
  });
}

void main() {
  testEarlyClose1();
  testEarlyClose2();
  testEarlyClose3();
}
