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

// @dart = 2.9

/// @assertion void writeAll(
///  Iterable objects, [
///  String separator = ""
///  ])
/// Iterates over the given objects and writes them in sequence.
///
/// If separator is provided, a write with the separator is performed between any
/// two elements of objects`.
///
/// This operation is non-blocking. See flush or done for how to get any errors
/// generated by this call.
/// @description Checks that If separator is provided, a write with the separator
/// is performed between any two elements of objects. Test non-string objects
/// @author sgrekhov@unipro.ru

import "dart:io";
import "../../../Utils/expect.dart";

var localhost = InternetAddress.loopbackIPv4.address;

class C {
  String toString() {
    return "This is C";
  }
}

test(String method) async {
  asyncStart();
  Iterable objects = [1, "2", 3.14, new C(), null];
  HttpServer server = await HttpServer.bind(localhost, 0);
  server.listen((HttpRequest request) {
    request.toList().then((List<List<int>> l) {
      Expect.equals("1 2 3.14 This is C null", new String.fromCharCodes(l[0]));
      request.response.close();
      server.close();
      asyncEnd();
    });
  });

  HttpClient client = new HttpClient();
  client.open(method, localhost, server.port, "")
      .then((HttpClientRequest request) {
    request.contentLength = 23;
    request.writeAll(objects, " ");
    return request.close();
  });
}

main() {
  test("get");
  test("head");
  test("delete");
  test("put");
  test("post");
  test("patch");
}
