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

// @dart = 2.9

// VMOptions=
// VMOptions=--short_socket_read
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write

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

// Client makes a HTTP 1.0 request without connection keep alive. The
// server sets a content length but still needs to close the
// connection as there is no keep alive.
void testHttp10NoKeepAlive() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((HttpRequest request) {
      Expect.isNull(request.headers.value('content-length'));
      Expect.equals(-1, request.contentLength);
      var response = request.response;
      response.contentLength = 1;
      Expect.equals("1.0", request.protocolVersion);
      response.done
          .then((_) => Expect.fail("Unexpected response completion"))
          .catchError((error) => Expect.isTrue(error is HttpException));
      response.write("Z");
      response.write("Z");
      response.close();
      Expect.throws(() {
        response.write("x");
      }, (e) => e is StateError);
    }, onError: (e, trace) {
      String msg = "Unexpected error $e";
      if (trace != null) msg += "\nStackTrace: $trace";
      Expect.fail(msg);
    });

    int count = 0;
    makeRequest() {
      Socket.connect("127.0.0.1", server.port).then((socket) {
        socket.write("GET / HTTP/1.0\r\n\r\n");

        List<int> response = [];
        socket.listen(response.addAll, onDone: () {
          count++;
          socket.destroy();
          String s = new String.fromCharCodes(response).toLowerCase();
          Expect.equals(-1, s.indexOf("keep-alive"));
          if (count < 10) {
            makeRequest();
          } else {
            server.close();
          }
        });
      });
    }

    makeRequest();
  });
}

// Client makes a HTTP 1.0 request and the server does not set a
// content length so it has to close the connection to mark the end of
// the response.
void testHttp10ServerClose() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((HttpRequest request) {
      Expect.isNull(request.headers.value('content-length'));
      Expect.equals(-1, request.contentLength);
      request.listen((_) {}, onDone: () {
        var response = request.response;
        Expect.equals("1.0", request.protocolVersion);
        response.write("Z");
        response.close();
      });
    }, onError: (e, trace) {
      String msg = "Unexpected error $e";
      if (trace != null) msg += "\nStackTrace: $trace";
      Expect.fail(msg);
    });

    int count = 0;
    makeRequest() {
      Socket.connect("127.0.0.1", server.port).then((socket) {
        socket.write("GET / HTTP/1.0\r\n");
        socket.write("Connection: Keep-Alive\r\n\r\n");

        List<int> response = [];
        socket.listen(response.addAll,
            onDone: () {
              socket.destroy();
              count++;
              String s = new String.fromCharCodes(response).toLowerCase();
              Expect.equals("z", s[s.length - 1]);
              Expect.equals(-1, s.indexOf("content-length:"));
              Expect.equals(-1, s.indexOf("keep-alive"));
              if (count < 10) {
                makeRequest();
              } else {
                server.close();
              }
            },
            onError: (e) => print(e));
      });
    }

    makeRequest();
  });
}

// Client makes a HTTP 1.0 request with connection keep alive. The
// server sets a content length so the persistent connection can be
// used.
void testHttp10KeepAlive() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((HttpRequest request) {
      Expect.isNull(request.headers.value('content-length'));
      Expect.equals(-1, request.contentLength);
      var response = request.response;
      response.contentLength = 1;
      response.persistentConnection = true;
      Expect.equals("1.0", request.protocolVersion);
      response.write("Z");
      response.close();
    }, onError: (e, trace) {
      String msg = "Unexpected error $e";
      if (trace != null) msg += "\nStackTrace: $trace";
      Expect.fail(msg);
    });

    Socket.connect("127.0.0.1", server.port).then((socket) {
      void sendRequest() {
        socket.write("GET / HTTP/1.0\r\n");
        socket.write("Connection: Keep-Alive\r\n\r\n");
      }

      List<int> response = [];
      int count = 0;
      socket.listen((d) {
        response.addAll(d);
        if (response[response.length - 1] == "Z".codeUnitAt(0)) {
          String s = new String.fromCharCodes(response).toLowerCase();
          Expect.isTrue(s.indexOf("\r\nconnection: keep-alive\r\n") > 0);
          Expect.isTrue(s.indexOf("\r\ncontent-length: 1\r\n") > 0);
          count++;
          if (count < 10) {
            response = [];
            sendRequest();
          } else {
            socket.close();
          }
        }
      }, onDone: () {
        socket.destroy();
        server.close();
      });
      sendRequest();
    });
  });
}

// Client makes a HTTP 1.0 request with connection keep alive. The
// server does not set a content length so it cannot honor connection
// keep alive.
void testHttp10KeepAliveServerCloses() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((HttpRequest request) {
      Expect.isNull(request.headers.value('content-length'));
      Expect.equals(-1, request.contentLength);
      var response = request.response;
      Expect.equals("1.0", request.protocolVersion);
      response.write("Z");
      response.close();
    }, onError: (e, trace) {
      String msg = "Unexpected error $e";
      if (trace != null) msg += "\nStackTrace: $trace";
      Expect.fail(msg);
    });

    int count = 0;
    makeRequest() {
      Socket.connect("127.0.0.1", server.port).then((socket) {
        socket.write("GET / HTTP/1.0\r\n");
        socket.write("Connection: Keep-Alive\r\n\r\n");

        List<int> response = [];
        socket.listen(response.addAll, onDone: () {
          socket.destroy();
          count++;
          String s = new String.fromCharCodes(response).toLowerCase();
          Expect.equals("z", s[s.length - 1]);
          Expect.equals(-1, s.indexOf("content-length"));
          Expect.equals(-1, s.indexOf("connection"));
          if (count < 10) {
            makeRequest();
          } else {
            server.close();
          }
        });
      });
    }

    makeRequest();
  });
}

void main() {
  testHttp10NoKeepAlive();
  testHttp10ServerClose();
  testHttp10KeepAlive();
  testHttp10KeepAliveServerCloses();
}
