// 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:isolate";
import "dart:io";
import "package:expect/expect.dart";

void testNoBody(int totalConnections, bool explicitContentLength) {
  int count = 0;
  HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
    server.listen((HttpRequest request) {
      Expect.equals(null, request.headers.value('content-length'));
      Expect.equals(-1, request.contentLength);
      var response = request.response;
      response.contentLength = 0;
      response.done.then((_) {
        Expect.fail("Unexpected successful response completion");
      }).catchError((error) {
        Expect.isTrue(error is HttpException);
        if (++count == totalConnections) {
          server.close();
        }
      });
      // write with content length 0 closes the connection and
      // reports an error.
      response.write("x");
      // Subsequent write are ignored as there is already an
      // error.
      response.write("x");
      // After an explicit close, write becomes a state error
      // because we have said we will not add more.
      response.close();
      Expect.throws(() {
        response.write("x");
      }, (e) => e is StateError);
    }, onError: (e, trace) {
      String msg = "Unexpected server error $e";
      if (trace != null) msg += "\nStackTrace: $trace";
      Expect.fail(msg);
    });

    HttpClient client = new HttpClient();
    for (int i = 0; i < totalConnections; i++) {
      client.get("127.0.0.1", server.port, "/").then((request) {
        if (explicitContentLength) {
          request.contentLength = 0;
        }
        return request.close();
      }).then((response) {
        Expect.equals("0", response.headers.value('content-length'));
        Expect.equals(0, response.contentLength);
        response.drain();
      }).catchError((e, trace) {
        // It's also okay to fail, as headers may not be written.
      });
    }
  });
}

void testBody(int totalConnections, bool useHeader) {
  HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
    int serverCount = 0;
    server.listen((HttpRequest request) {
      Expect.equals("2", request.headers.value('content-length'));
      Expect.equals(2, request.contentLength);
      var response = request.response;
      if (useHeader) {
        response.contentLength = 2;
      } else {
        response.headers.set("content-length", 2);
      }
      request.listen((d) {}, onDone: () {
        response.write("x");
        Expect.throws(
            () => response.contentLength = 3, (e) => e is HttpException);
        response.write("x");
        response.write("x");
        response.done.then((_) {
          Expect.fail("Unexpected successful response completion");
        }).catchError((error) {
          Expect.isTrue(error is HttpException, "[$error]");
          if (++serverCount == totalConnections) {
            server.close();
          }
        });
        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 clientCount = 0;
    HttpClient client = new HttpClient();
    for (int i = 0; i < totalConnections; i++) {
      client.get("127.0.0.1", server.port, "/").then((request) {
        if (useHeader) {
          request.contentLength = 2;
        } else {
          request.headers.add(HttpHeaders.contentLengthHeader, "7");
          request.headers.add(HttpHeaders.contentLengthHeader, "2");
        }
        request.write("x");
        Expect.throws(
            () => request.contentLength = 3, (e) => e is HttpException);
        request.write("x");
        return request.close();
      }).then((response) {
        Expect.equals("2", response.headers.value('content-length'));
        Expect.equals(2, response.contentLength);
        response.listen((d) {}, onDone: () {
          if (++clientCount == totalConnections) {
            client.close();
          }
        }, onError: (error, trace) {
          // Undefined what server response sends.
        });
      }).catchError((error) {
        // It's also okay to fail, as headers may not be written.
      });
    }
  });
}

void testBodyChunked(int totalConnections, bool useHeader) {
  HttpServer.bind("127.0.0.1", 0, backlog: totalConnections).then((server) {
    server.listen((HttpRequest request) {
      Expect.isNull(request.headers.value('content-length'));
      Expect.equals(-1, request.contentLength);
      var response = request.response;
      if (useHeader) {
        response.contentLength = 2;
        response.headers.chunkedTransferEncoding = true;
      } else {
        response.headers.set("content-length", 2);
        response.headers.set("transfer-encoding", "chunked");
      }
      request.listen((d) {}, onDone: () {
        response.write("x");
        Expect.throws(() => response.headers.chunkedTransferEncoding = false,
            (e) => e is HttpException);
        response.write("x");
        response.write("x");
        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;
    HttpClient client = new HttpClient();
    for (int i = 0; i < totalConnections; i++) {
      client.get("127.0.0.1", server.port, "/").then((request) {
        if (useHeader) {
          request.contentLength = 2;
          request.headers.chunkedTransferEncoding = true;
        } else {
          request.headers.add(HttpHeaders.contentLengthHeader, "2");
          request.headers.set(HttpHeaders.transferEncodingHeader, "chunked");
        }
        request.write("x");
        Expect.throws(() => request.headers.chunkedTransferEncoding = false,
            (e) => e is HttpException);
        request.write("x");
        request.write("x");
        return request.close();
      }).then((response) {
        Expect.isNull(response.headers.value('content-length'));
        Expect.equals(-1, response.contentLength);
        response.listen((d) {}, onDone: () {
          if (++count == totalConnections) {
            client.close();
            server.close();
          }
        });
      }).catchError((e, trace) {
        String msg = "Unexpected error $e";
        if (trace != null) msg += "\nStackTrace: $trace";
        Expect.fail(msg);
      });
    }
  });
}

void testSetContentLength() {
  HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((HttpRequest request) {
      var response = request.response;
      Expect.isNull(response.headers.value('content-length'));
      Expect.equals(-1, response.contentLength);
      response.headers.set("content-length", 3);
      Expect.equals("3", response.headers.value('content-length'));
      Expect.equals(3, response.contentLength);
      response.write("xxx");
      response.close();
    });

    var client = new HttpClient();
    client
        .get("127.0.0.1", server.port, "/")
        .then((request) => request.close())
        .then((response) {
      response.listen((_) {}, onDone: () {
        client.close();
        server.close();
      });
    });
  });
}

void main() {
  testNoBody(5, false);
  testNoBody(25, false);
  testNoBody(5, true);
  testNoBody(25, true);
  testBody(5, false);
  testBody(5, true);
  testBodyChunked(5, false);
  testBodyChunked(5, true);
  testSetContentLength();
}
