// Copyright (c) 2018, 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.

import "dart:async";

import 'package:http_io/http_io.dart';
import 'package:test/test.dart';

Future<int> getData(HttpClient client, int port, bool chunked, int length) {
  return client
      .get("127.0.0.1", port, "/?chunked=$chunked&length=$length")
      .then((request) => request.close())
      .then((response) {
    return response.fold(0, (bytes, data) => bytes + data.length).then((bytes) {
      expect(length, equals(bytes));
    });
  });
}

Future<HttpServer> startServer() {
  return HttpServer.bind("127.0.0.1", 0).then((server) {
    server.listen((request) {
      bool chunked = request.uri.queryParameters["chunked"] == "true";
      int length = int.parse(request.uri.queryParameters["length"]);
      var buffer = new List<int>.filled(length, 0);
      if (!chunked) request.response.contentLength = length;
      request.response.add(buffer);
      request.response.close();
    });
    return server;
  });
}

Future<Null> testKeepAliveNonChunked() {
  final completer = new Completer<Null>();
  startServer().then((server) {
    var client = new HttpClient();

    getData(client, server.port, false, 100)
        .then((_) => getData(client, server.port, false, 100))
        .then((_) => getData(client, server.port, false, 100))
        .then((_) => getData(client, server.port, false, 100))
        .then((_) => getData(client, server.port, false, 100))
        .then((_) {
      server.close();
      client.close();
      completer.complete();
    });
  });
  return completer.future;
}

Future<Null> testKeepAliveChunked() {
  final completer = new Completer<Null>();
  startServer().then((server) {
    var client = new HttpClient();

    getData(client, server.port, true, 100)
        .then((_) => getData(client, server.port, true, 100))
        .then((_) => getData(client, server.port, true, 100))
        .then((_) => getData(client, server.port, true, 100))
        .then((_) => getData(client, server.port, true, 100))
        .then((_) {
      server.close();
      client.close();
      completer.complete();
    });
  });
  return completer.future;
}

Future<Null> testKeepAliveMixed() {
  final completer = new Completer<Null>();
  startServer().then((server) {
    var client = new HttpClient();

    getData(client, server.port, true, 100)
        .then((_) => getData(client, server.port, false, 100))
        .then((_) => getData(client, server.port, true, 100))
        .then((_) => getData(client, server.port, false, 100))
        .then((_) => getData(client, server.port, true, 100))
        .then((_) => getData(client, server.port, false, 100))
        .then((_) => getData(client, server.port, true, 100))
        .then((_) => getData(client, server.port, false, 100))
        .then((_) {
      server.close();
      client.close();
      completer.complete();
    });
  });
  return completer.future;
}

void main() {
  test('keepAliveNonChunked', testKeepAliveNonChunked);
  test('keepAliveChunked', testKeepAliveChunked);
  test('keepAliveMixed', testKeepAliveMixed);
}
