Migrate more tests (#13)

diff --git a/test/http_auth_test.dart b/test/http_auth_test.dart
new file mode 100644
index 0000000..1942781
--- /dev/null
+++ b/test/http_auth_test.dart
@@ -0,0 +1,229 @@
+// 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.
+
+import 'dart:async';
+import 'dart:convert';
+
+import "package:http_io/http_io.dart";
+import "package:test/test.dart";
+
+class Server {
+  HttpServer server;
+  bool passwordChanged = false;
+
+  Future<Server> start() {
+    var completer = new Completer<Server>();
+    HttpServer.bind("127.0.0.1", 0).then((s) {
+      server = s;
+      server.listen((HttpRequest request) {
+        var response = request.response;
+        if (request.uri.path == "/passwdchg") {
+          passwordChanged = true;
+          response.close();
+          return;
+        }
+
+        String username;
+        String password;
+        if (request.uri.path == "/") {
+          username = "username";
+          password = "password";
+        } else {
+          username = request.uri.path.substring(1, 6);
+          password = request.uri.path.substring(1, 6);
+        }
+        if (passwordChanged) password = "${password}1";
+        if (request.headers[HttpHeaders.AUTHORIZATION] != null) {
+          expect(1, equals(request.headers[HttpHeaders.AUTHORIZATION].length));
+          String authorization = request.headers[HttpHeaders.AUTHORIZATION][0];
+          List<String> tokens = authorization.split(" ");
+          expect("Basic", equals(tokens[0]));
+          String auth = BASE64.encode(UTF8.encode("$username:$password"));
+          if (passwordChanged && auth != tokens[1]) {
+            response.statusCode = HttpStatus.UNAUTHORIZED;
+            response.headers
+                .set(HttpHeaders.WWW_AUTHENTICATE, "Basic, realm=realm");
+          } else {
+            expect(auth, equals(tokens[1]));
+          }
+        } else {
+          response.statusCode = HttpStatus.UNAUTHORIZED;
+          response.headers
+              .set(HttpHeaders.WWW_AUTHENTICATE, "Basic, realm=realm");
+        }
+        response.close();
+      });
+      completer.complete(this);
+    });
+    return completer.future;
+  }
+
+  void shutdown() {
+    server.close();
+  }
+
+  int get port => server.port;
+}
+
+Future<Server> setupServer() {
+  return new Server().start();
+}
+
+Future<Null> testUrlUserInfo() {
+  Completer<Null> completer = new Completer();
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    client
+        .getUrl(Uri.parse("http://username:password@127.0.0.1:${server.port}/"))
+        .then((request) => request.close())
+        .then((HttpClientResponse response) {
+      response.listen((_) {}, onDone: () {
+        server.shutdown();
+        client.close();
+        completer.complete(null);
+      });
+    });
+  });
+  return completer.future;
+}
+
+Future<Null> testBasicNoCredentials() {
+  Completer<Null> completer = new Completer();
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        expect(HttpStatus.UNAUTHORIZED, equals(response.statusCode));
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    var futures = <Future>[];
+    for (int i = 0; i < 5; i++) {
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i")));
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx")));
+    }
+    Future.wait(futures).then((_) {
+      server.shutdown();
+      client.close();
+      completer.complete(null);
+    });
+  });
+  return completer.future;
+}
+
+Future<Null> testBasicCredentials() {
+  Completer<Null> completer = new Completer();
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        expect(HttpStatus.OK, equals(response.statusCode));
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    for (int i = 0; i < 5; i++) {
+      client.addCredentials(Uri.parse("http://127.0.0.1:${server.port}/test$i"),
+          "realm", new HttpClientBasicCredentials("test$i", "test$i"));
+    }
+
+    var futures = <Future>[];
+    for (int i = 0; i < 5; i++) {
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i")));
+      futures.add(
+          makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx")));
+    }
+    Future.wait(futures).then((_) {
+      server.shutdown();
+      client.close();
+      completer.complete(null);
+    });
+  });
+  return completer.future;
+}
+
+Future<Null> testBasicAuthenticateCallback() {
+  Completer<Null> completer = new Completer();
+  setupServer().then((server) {
+    HttpClient client = new HttpClient();
+    bool passwordChanged = false;
+
+    client.authenticate = (Uri url, String scheme, String realm) {
+      expect("Basic", equals(scheme));
+      expect("realm", equals(realm));
+      String username = url.path.substring(1, 6);
+      String password = url.path.substring(1, 6);
+      if (passwordChanged) password = "${password}1";
+      Completer completer = new Completer();
+      new Timer(const Duration(milliseconds: 10), () {
+        client.addCredentials(
+            url, realm, new HttpClientBasicCredentials(username, password));
+        completer.complete(true);
+      });
+      return completer.future;
+    };
+
+    Future makeRequest(Uri url) {
+      return client
+          .getUrl(url)
+          .then((HttpClientRequest request) => request.close())
+          .then((HttpClientResponse response) {
+        expect(HttpStatus.OK, equals(response.statusCode));
+        return response.fold(null, (x, y) {});
+      });
+    }
+
+    List<Future> makeRequests() {
+      var futures = <Future>[];
+      for (int i = 0; i < 5; i++) {
+        futures.add(
+            makeRequest(Uri.parse("http://127.0.0.1:${server.port}/test$i")));
+        futures.add(makeRequest(
+            Uri.parse("http://127.0.0.1:${server.port}/test$i/xxx")));
+      }
+      return futures;
+    }
+
+    Future.wait(makeRequests()).then((_) {
+      makeRequest(Uri.parse("http://127.0.0.1:${server.port}/passwdchg"))
+          .then((_) {
+        passwordChanged = true;
+        Future.wait(makeRequests()).then((_) {
+          server.shutdown();
+          client.close();
+          completer.complete(null);
+        });
+      });
+    });
+  });
+  return completer.future;
+}
+
+main() {
+  test("UrlUserInfo", () async {
+    await testUrlUserInfo();
+  });
+  test("BasicNoCredentials", () async {
+    await testBasicNoCredentials();
+  });
+  test("BasicCredentials", () async {
+    await testBasicCredentials();
+  });
+  test("BasicAuthenticateCallback", () async {
+    await testBasicAuthenticateCallback();
+  });
+}
diff --git a/test/http_bind_test.dart b/test/http_bind_test.dart
new file mode 100644
index 0000000..ce4c773
--- /dev/null
+++ b/test/http_bind_test.dart
@@ -0,0 +1,90 @@
+// 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.
+
+import 'dart:async';
+import 'dart:io' hide HttpClient, HttpServer;
+
+import "package:http_io/http_io.dart";
+import "package:test/test.dart";
+
+Future<Null> testBindShared(String host, bool v6Only) async {
+  // Sent a single request using a new HttpClient to ensure a new TCP
+  // connection is used.
+  Future singleRequest(host, port, statusCode) async {
+    var client = new HttpClient();
+    var request = await client.open('GET', host, port, '/');
+    var response = await request.close();
+    await response.drain();
+    expect(statusCode, equals(response.statusCode));
+    client.close(force: true);
+  }
+
+  Completer server1Request = new Completer();
+  Completer server2Request = new Completer();
+
+  var server1 = await HttpServer.bind(host, 0, v6Only: v6Only, shared: true);
+  var port = server1.port;
+  expect(port > 0, isTrue);
+
+  var server2 = await HttpServer.bind(host, port, v6Only: v6Only, shared: true);
+  expect(server1.address.address, equals(server2.address.address));
+  expect(port, equals(server2.port));
+
+  server1.listen((request) {
+    server1Request.complete();
+    request.response.statusCode = 501;
+    request.response.close();
+  });
+
+  await singleRequest(host, port, 501);
+  await server1.close();
+
+  server2.listen((request) {
+    server2Request.complete();
+    request.response.statusCode = 502;
+    request.response.close();
+  });
+
+  await singleRequest(host, port, 502);
+  await server2.close();
+
+  await server1Request.future;
+  await server2Request.future;
+}
+
+void main() {
+  test("BindShared ipv4 not v6only", () async {
+    const String host = '127.0.0.1';
+    await testBindShared(host, false);
+  });
+
+  test("BindShared ipv4 v6only", () async {
+    const String host = '127.0.0.1';
+    await testBindShared(host, true);
+  });
+
+  test("BindShared ipv6 not v6only", () async {
+    bool useIPv6 = await supportsIPV6();
+    if (!useIPv6) return;
+    const String host = '::1';
+    await testBindShared(host, false);
+  });
+
+  test("BindShared ipv6 v6only", () async {
+    bool useIPv6 = await supportsIPV6();
+    if (!useIPv6) return;
+    const String host = '::1';
+    await testBindShared(host, true);
+  });
+}
+
+Future<bool> supportsIPV6() async {
+  try {
+    var socket = await ServerSocket.bind('::1', 0);
+    await socket.close();
+    return true;
+  } catch (e) {
+    return false;
+  }
+}