Adds http_client_stays_alive_test.dart (#22)

diff --git a/test/http_client_stays_alive_test.dart b/test/http_client_stays_alive_test.dart
new file mode 100644
index 0000000..131c289
--- /dev/null
+++ b/test/http_client_stays_alive_test.dart
@@ -0,0 +1,95 @@
+// 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.
+
+// OtherResources=http_client_stays_alive_test.dart
+
+import 'dart:async';
+import 'dart:io' hide HttpServer, HttpRequest, HttpClient;
+
+import "package:http_io/http_io.dart";
+import "package:test/test.dart";
+
+// NOTE: This test tries to ensure that an HttpClient will close it's
+// underlying idle connections after [HttpClient.idleTimeout].
+//
+// The main script spawns a server and a subprocess which does a connection back
+// to it.
+// The subprocess is expected to shut down its idle sockets after
+// [HttpClient.idleTimeout] and the main script will assert that this happens
+// within +/- 2 <= seconds.
+
+const SECONDS = 4;
+
+List<String> packageOptions() {
+  if (Platform.packageRoot != null) {
+    return <String>['--package-root=${Platform.packageRoot}'];
+  } else if (Platform.packageConfig != null) {
+    return <String>['--packages=${Platform.packageConfig}'];
+  } else {
+    return <String>[];
+  }
+}
+
+Future<Null> runServerProcess() {
+  Completer<Null> completer = new Completer();
+  HttpServer.bind('127.0.0.1', 0).then((server) {
+    var url = 'http://127.0.0.1:${server.port}/';
+
+    server.idleTimeout = const Duration(hours: 1);
+
+    var subscription = server.listen((HttpRequest request) {
+      request.response
+        ..write('hello world')
+        ..close();
+    });
+
+    var sw = new Stopwatch()..start();
+    var script =
+        "${Directory.current.path}/test/http_client_stays_alive_test.dart";
+
+    var arguments = packageOptions()..add(script);
+    Process.run(Platform.executable, arguments, environment: {'URL': url}).then(
+        (res) {
+      subscription.cancel();
+      if (res.exitCode != 0) {
+        throw "Child exited with ${res.exitCode} instead of 0. "
+            "(stdout: ${res.stdout}, stderr: ${res.stderr})";
+      }
+      var seconds = sw.elapsed.inSeconds;
+      // NOTE: There is a slight chance this will cause flakiness, but there is
+      // no other good way of testing correctness of timing-dependent code
+      // form the outside.
+      if (seconds < SECONDS || (SECONDS + 30) < seconds) {
+        throw "Child did exit within $seconds seconds, but expected it to take "
+            "roughly $SECONDS seconds.";
+      }
+
+      completer.complete(null);
+    });
+  });
+  return completer.future;
+}
+
+runClientProcess(String url) {
+  var uri = Uri.parse(url);
+
+  // NOTE: We make an HTTP client request and then *forget to close* the HTTP
+  // client instance. The idle timer should fire after SECONDS.
+  var client = new HttpClient();
+  client.idleTimeout = const Duration(seconds: SECONDS);
+
+  client
+      .getUrl(uri)
+      .then((req) => req.close())
+      .then((response) => response.drain())
+      .then((_) => print('drained client request'));
+}
+
+main() {
+  if (Platform.environment['URL'] != null) {
+    runClientProcess(Platform.environment['URL']);
+  } else {
+    test("ClientStaysAlive", runServerProcess);
+  }
+}