about summary refs log tree commit diff
path: root/src/rt/libuv/test
diff options
context:
space:
mode:
authorRob Arnold <robarnold@cs.cmu.edu>2011-07-08 17:22:48 -0700
committerBrian Anderson <banderson@mozilla.com>2011-08-05 11:57:06 -0700
commit8229c3fa752c7fca3760245da4e23ba67acdee33 (patch)
treeed2e83518503b901cadcb3dbac01f4a0dad67023 /src/rt/libuv/test
parentf4b87c749fc5dc085cd31ba3b5f91f11d863e0fa (diff)
downloadrust-8229c3fa752c7fca3760245da4e23ba67acdee33.tar.gz
rust-8229c3fa752c7fca3760245da4e23ba67acdee33.zip
Update libuv to revision ee599ec1141cc48f895de1f9d148033babdf9c2a
Diffstat (limited to 'src/rt/libuv/test')
-rw-r--r--src/rt/libuv/test/benchmark-ares.c116
-rw-r--r--src/rt/libuv/test/benchmark-getaddrinfo.c92
-rw-r--r--src/rt/libuv/test/benchmark-list.h8
-rw-r--r--src/rt/libuv/test/benchmark-ping-pongs.c12
-rw-r--r--src/rt/libuv/test/benchmark-pump.c32
-rw-r--r--src/rt/libuv/test/benchmark-sizes.c16
-rw-r--r--src/rt/libuv/test/dns-server.c325
-rw-r--r--src/rt/libuv/test/echo-server.c60
-rw-r--r--src/rt/libuv/test/runner-unix.c4
-rw-r--r--src/rt/libuv/test/test-async.c14
-rw-r--r--src/rt/libuv/test/test-bind-error.c37
-rw-r--r--src/rt/libuv/test/test-bind6-error.c164
-rw-r--r--src/rt/libuv/test/test-callback-stack.c28
-rw-r--r--src/rt/libuv/test/test-connection-fail.c12
-rw-r--r--src/rt/libuv/test/test-delayed-accept.c37
-rw-r--r--src/rt/libuv/test/test-get-currentexe.c10
-rw-r--r--src/rt/libuv/test/test-getaddrinfo.c110
-rw-r--r--src/rt/libuv/test/test-gethostbyname.c192
-rw-r--r--src/rt/libuv/test/test-hrtime.c54
-rw-r--r--src/rt/libuv/test/test-list.h34
-rw-r--r--src/rt/libuv/test/test-loop-handles.c26
-rw-r--r--src/rt/libuv/test/test-ping-pong.c52
-rw-r--r--src/rt/libuv/test/test-shutdown-eof.c32
-rw-r--r--src/rt/libuv/test/test-tcp-writealot.c18
-rw-r--r--src/rt/libuv/test/test-timer-again.c16
-rw-r--r--src/rt/libuv/test/test-timer.c12
26 files changed, 1352 insertions, 161 deletions
diff --git a/src/rt/libuv/test/benchmark-ares.c b/src/rt/libuv/test/benchmark-ares.c
new file mode 100644
index 00000000000..c3f538bff95
--- /dev/null
+++ b/src/rt/libuv/test/benchmark-ares.c
@@ -0,0 +1,116 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h> /* strlen */
+
+ares_channel channel;
+struct ares_options options;
+int optmask;
+
+struct in_addr testsrv;
+
+int ares_callbacks;
+int ares_errors;
+int argument;
+
+#define NUM_CALLS_TO_START    1000
+
+static int64_t start_time;
+static int64_t end_time;
+
+/* callback method. may issue another call */
+static void aresbynamecallback( void *arg,
+                          int status,
+                          int timeouts,
+                          struct hostent *hostent) {
+    ares_callbacks++;
+    if (status != 0) {
+      ares_errors++;
+    }
+
+}
+
+
+static void prep_tcploopback()
+{
+  /* for test, use echo server - TCP port TEST_PORT on loopback */
+  struct sockaddr_in test_server = uv_ip4_addr("127.0.0.1", 0);
+  int rc = 0;
+  optmask = 0;
+
+  optmask = ARES_OPT_SERVERS | ARES_OPT_TCP_PORT | ARES_OPT_FLAGS;
+  options.servers = &test_server.sin_addr;
+  options.nservers = 1;
+  options.tcp_port = htons(TEST_PORT_2);
+  options.flags = ARES_FLAG_USEVC;
+
+  rc = uv_ares_init_options(&channel, &options, optmask);
+
+  ASSERT(rc == ARES_SUCCESS);
+}
+
+
+BENCHMARK_IMPL(gethostbyname) {
+
+  int rc = 0;
+  int ares_start;;
+
+  rc = ares_library_init(ARES_LIB_INIT_ALL);
+  if (rc != 0) {
+    printf("ares library init fails %d\n", rc);
+    return 1;
+  }
+
+  uv_init();
+  ares_callbacks = 0;
+  ares_errors = 0;
+
+  uv_update_time();
+  start_time = uv_now();
+
+  prep_tcploopback();
+
+  for (ares_start = 0; ares_start < NUM_CALLS_TO_START; ares_start++) {
+    ares_gethostbyname(channel,
+                      "echos.srv",
+                      AF_INET,
+                      &aresbynamecallback,
+                      &argument);
+  }
+
+  uv_run();
+
+  uv_ares_destroy(channel);
+
+  end_time = uv_now();
+
+  if (ares_errors > 0) {
+    printf("There were %d failures\n", ares_errors);
+  }
+  LOGF("ares_gethostbyname: %d calls in %d ms \n", ares_callbacks, (int) (end_time - start_time));
+
+  return 0;
+}
diff --git a/src/rt/libuv/test/benchmark-getaddrinfo.c b/src/rt/libuv/test/benchmark-getaddrinfo.c
new file mode 100644
index 00000000000..ba859c3c82e
--- /dev/null
+++ b/src/rt/libuv/test/benchmark-getaddrinfo.c
@@ -0,0 +1,92 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h> /* strlen */
+
+
+#define CONCURRENT_CALLS 10
+#define TOTAL_CALLS 10000
+
+const char* name = "localhost";
+
+static uv_getaddrinfo_t handles[CONCURRENT_CALLS];
+
+static int calls_initiated = 0;
+static int calls_completed = 0;
+static int64_t start_time;
+static int64_t end_time;
+
+
+static void getaddrinfo_initiate(uv_getaddrinfo_t* handle);
+
+
+static void getaddrinfo_cb(uv_getaddrinfo_t* handle, int status,
+    struct addrinfo* res) {
+  ASSERT(status == 0);
+  calls_completed++;
+  if (calls_initiated < TOTAL_CALLS) {
+    getaddrinfo_initiate(handle);
+  }
+}
+
+
+static void getaddrinfo_initiate(uv_getaddrinfo_t* handle) {
+  int r;
+
+  calls_initiated++;
+
+  r = uv_getaddrinfo(handle, &getaddrinfo_cb, name, NULL, NULL);
+  ASSERT(r == 0);
+}
+
+
+BENCHMARK_IMPL(getaddrinfo) {
+  int i;
+
+  uv_init();
+
+  uv_update_time();
+  start_time = uv_now();
+
+  for (i = 0; i < CONCURRENT_CALLS; i++) {
+    getaddrinfo_initiate(&handles[i]);
+  }
+
+  uv_run();
+
+  uv_update_time();
+  end_time = uv_now();
+
+  ASSERT(calls_initiated == TOTAL_CALLS);
+  ASSERT(calls_completed == TOTAL_CALLS);
+
+  LOGF("getaddrinfo: %d calls in %d ms (%.0f requests/second)\n",
+       calls_completed,
+       (int) (end_time - start_time),
+       (double) calls_completed / (double) (end_time - start_time) * 1000.0);
+
+  return 0;
+}
diff --git a/src/rt/libuv/test/benchmark-list.h b/src/rt/libuv/test/benchmark-list.h
index 33ef97e260e..6040e90a326 100644
--- a/src/rt/libuv/test/benchmark-list.h
+++ b/src/rt/libuv/test/benchmark-list.h
@@ -23,8 +23,11 @@ BENCHMARK_DECLARE (sizes)
 BENCHMARK_DECLARE (ping_pongs)
 BENCHMARK_DECLARE (pump100_client)
 BENCHMARK_DECLARE (pump1_client)
+BENCHMARK_DECLARE (gethostbyname)
+BENCHMARK_DECLARE (getaddrinfo)
 HELPER_DECLARE    (pump_server)
 HELPER_DECLARE    (echo_server)
+HELPER_DECLARE    (dns_server)
 
 TASK_LIST_START
   BENCHMARK_ENTRY  (sizes)
@@ -37,4 +40,9 @@ TASK_LIST_START
 
   BENCHMARK_ENTRY  (pump1_client)
   BENCHMARK_HELPER (pump1_client, pump_server)
+
+  BENCHMARK_ENTRY  (gethostbyname)
+  BENCHMARK_HELPER (gethostbyname, dns_server)
+
+  BENCHMARK_ENTRY  (getaddrinfo)
 TASK_LIST_END
diff --git a/src/rt/libuv/test/benchmark-ping-pongs.c b/src/rt/libuv/test/benchmark-ping-pongs.c
index 9b5543251cb..7124a3614a4 100644
--- a/src/rt/libuv/test/benchmark-ping-pongs.c
+++ b/src/rt/libuv/test/benchmark-ping-pongs.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 
 #include <stdlib.h>
@@ -52,7 +52,7 @@ static int completed_pingers = 0;
 static int64_t start_time;
 
 
-static uv_buf_t buf_alloc(uv_tcp_t* tcp, size_t size) {
+static uv_buf_t buf_alloc(uv_stream_t* tcp, size_t size) {
   buf_t* ab;
 
   ab = buf_freelist;
@@ -125,7 +125,7 @@ static void pinger_shutdown_cb(uv_handle_t* handle, int status) {
 }
 
 
-static void pinger_read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
+static void pinger_read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
   unsigned int i;
   pinger_t* pinger;
 
@@ -171,7 +171,7 @@ static void pinger_connect_cb(uv_req_t *req, int status) {
 
   pinger_write_ping(pinger);
 
-  if (uv_read_start((uv_tcp_t*)(req->handle), buf_alloc, pinger_read_cb)) {
+  if (uv_read_start((uv_stream_t*)(req->handle), buf_alloc, pinger_read_cb)) {
     FATAL("uv_read_start failed");
   }
 }
@@ -198,8 +198,8 @@ static void pinger_new() {
   uv_req_init(&pinger->connect_req, (uv_handle_t*)&pinger->tcp,
       pinger_connect_cb);
 
-  uv_bind(&pinger->tcp, client_addr);
-  r = uv_connect(&pinger->connect_req, server_addr);
+  uv_tcp_bind(&pinger->tcp, client_addr);
+  r = uv_tcp_connect(&pinger->connect_req, server_addr);
   ASSERT(!r);
 }
 
diff --git a/src/rt/libuv/test/benchmark-pump.c b/src/rt/libuv/test/benchmark-pump.c
index 8a8f52a79d0..cd9c7d99679 100644
--- a/src/rt/libuv/test/benchmark-pump.c
+++ b/src/rt/libuv/test/benchmark-pump.c
@@ -20,7 +20,7 @@
  */
 
 #include "task.h"
-#include "../uv.h"
+#include "uv.h"
 
 #include <math.h>
 #include <stdio.h>
@@ -35,13 +35,13 @@ static int TARGET_CONNECTIONS;
 #define STATS_COUNT                 5
 
 
-static void do_write(uv_tcp_t*);
+static void do_write(uv_stream_t*);
 static void maybe_connect_some();
 
 static uv_req_t* req_alloc();
 static void req_free(uv_req_t* uv_req);
 
-static uv_buf_t buf_alloc(uv_tcp_t*, size_t size);
+static uv_buf_t buf_alloc(uv_stream_t*, size_t size);
 static void buf_free(uv_buf_t uv_buf_t);
 
 
@@ -79,7 +79,7 @@ static double gbit(int64_t bytes, int64_t passed_ms) {
 }
 
 
-static void show_stats(uv_handle_t *handle, int status) {
+static void show_stats(uv_timer_t* handle, int status) {
   int64_t diff;
 
 #if PRINT_STATS
@@ -154,7 +154,7 @@ static void start_stats_collection() {
 }
 
 
-static void read_cb(uv_tcp_t* tcp, ssize_t bytes, uv_buf_t buf) {
+static void read_cb(uv_stream_t* tcp, ssize_t bytes, uv_buf_t buf) {
   if (nrecv_total == 0) {
     ASSERT(start_time == 0);
     uv_update_time();
@@ -183,11 +183,11 @@ static void write_cb(uv_req_t *req, int status) {
   nsent += sizeof write_buffer;
   nsent_total += sizeof write_buffer;
 
-  do_write((uv_tcp_t*)req->handle);
+  do_write((uv_stream_t*)req->handle);
 }
 
 
-static void do_write(uv_tcp_t* tcp) {
+static void do_write(uv_stream_t* tcp) {
   uv_req_t* req;
   uv_buf_t buf;
   int r;
@@ -221,7 +221,7 @@ static void connect_cb(uv_req_t* req, int status) {
 
     /* Yay! start writing */
     for (i = 0; i < write_sockets; i++) {
-      do_write(&write_handles[i]);
+      do_write((uv_stream_t*)&write_handles[i]);
     }
   }
 }
@@ -241,27 +241,27 @@ static void maybe_connect_some() {
 
     req = req_alloc();
     uv_req_init(req, (uv_handle_t*)tcp, connect_cb);
-    r = uv_connect(req, connect_addr);
+    r = uv_tcp_connect(req, connect_addr);
     ASSERT(r == 0);
   }
 }
 
 
-static void connection_cb(uv_tcp_t* s, int status) {
+static void connection_cb(uv_handle_t* s, int status) {
   uv_tcp_t* tcp;
   int r;
 
-  ASSERT(&server == s);
+  ASSERT(&server == (uv_tcp_t*)s);
   ASSERT(status == 0);
 
   tcp = malloc(sizeof(uv_tcp_t));
 
   uv_tcp_init(tcp);
 
-  r = uv_accept(s, tcp);
+  r = uv_accept(s, (uv_stream_t*)tcp);
   ASSERT(r == 0);
 
-  r = uv_read_start(tcp, buf_alloc, read_cb);
+  r = uv_read_start((uv_stream_t*)tcp, buf_alloc, read_cb);
   ASSERT(r == 0);
 
   read_sockets++;
@@ -317,7 +317,7 @@ typedef struct buf_list_s {
 static buf_list_t* buf_freelist = NULL;
 
 
-static uv_buf_t buf_alloc(uv_tcp_t* tcp, size_t size) {
+static uv_buf_t buf_alloc(uv_stream_t* tcp, size_t size) {
   buf_list_t* buf;
 
   buf = buf_freelist;
@@ -351,9 +351,9 @@ HELPER_IMPL(pump_server) {
   /* Server */
   r = uv_tcp_init(&server);
   ASSERT(r == 0);
-  r = uv_bind(&server, listen_addr);
+  r = uv_tcp_bind(&server, listen_addr);
   ASSERT(r == 0);
-  r = uv_listen(&server, MAX_WRITE_HANDLES, connection_cb);
+  r = uv_tcp_listen(&server, MAX_WRITE_HANDLES, connection_cb);
   ASSERT(r == 0);
 
   uv_run();
diff --git a/src/rt/libuv/test/benchmark-sizes.c b/src/rt/libuv/test/benchmark-sizes.c
index a5f573feec6..830de3a007c 100644
--- a/src/rt/libuv/test/benchmark-sizes.c
+++ b/src/rt/libuv/test/benchmark-sizes.c
@@ -20,16 +20,16 @@
  */
 
 #include "task.h"
-#include "../uv.h"
+#include "uv.h"
 
 
 BENCHMARK_IMPL(sizes) {
-  LOGF("uv_req_t: %lu bytes\n", sizeof(uv_req_t));
-  LOGF("uv_tcp_t: %lu bytes\n", sizeof(uv_tcp_t));
-  LOGF("uv_prepare_t: %lu bytes\n", sizeof(uv_prepare_t));
-  LOGF("uv_check_t: %lu bytes\n", sizeof(uv_check_t));
-  LOGF("uv_idle_t: %lu bytes\n", sizeof(uv_idle_t));
-  LOGF("uv_async_t: %lu bytes\n", sizeof(uv_async_t));
-  LOGF("uv_timer_t: %lu bytes\n", sizeof(uv_timer_t));
+  LOGF("uv_req_t: %u bytes\n", (unsigned int) sizeof(uv_req_t));
+  LOGF("uv_tcp_t: %u bytes\n", (unsigned int) sizeof(uv_tcp_t));
+  LOGF("uv_prepare_t: %u bytes\n", (unsigned int) sizeof(uv_prepare_t));
+  LOGF("uv_check_t: %u bytes\n", (unsigned int) sizeof(uv_check_t));
+  LOGF("uv_idle_t: %u bytes\n", (unsigned int) sizeof(uv_idle_t));
+  LOGF("uv_async_t: %u bytes\n", (unsigned int) sizeof(uv_async_t));
+  LOGF("uv_timer_t: %u bytes\n", (unsigned int) sizeof(uv_timer_t));
   return 0;
 }
diff --git a/src/rt/libuv/test/dns-server.c b/src/rt/libuv/test/dns-server.c
new file mode 100644
index 00000000000..361c9d080ba
--- /dev/null
+++ b/src/rt/libuv/test/dns-server.c
@@ -0,0 +1,325 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+typedef struct {
+  uv_req_t req;
+  uv_buf_t buf;
+} write_req_t;
+
+
+/* used to track multiple DNS requests received */
+typedef struct {
+  char* prevbuf_ptr;
+  int prevbuf_pos;
+  int prevbuf_rem;
+} dnsstate;
+
+
+/* modify handle to append dnsstate */
+typedef struct {
+  uv_tcp_t handle;
+  dnsstate state;
+} dnshandle;
+
+
+static int server_closed;
+static uv_tcp_t server;
+
+
+static void after_write(uv_req_t* req, int status);
+static void after_read(uv_stream_t*, ssize_t nread, uv_buf_t buf);
+static void on_close(uv_handle_t* peer);
+static void on_server_close(uv_handle_t* handle);
+static void on_connection(uv_handle_t*, int status);
+
+#define WRITE_BUF_LEN   (64*1024)
+#define DNSREC_LEN      (4)
+
+#define LEN_OFFSET 0
+#define QUERYID_OFFSET 2
+unsigned char DNSRsp[] = {0, 43, 0, 0, 0x81, 0x80, 0, 1, 0, 1, 0, 0, 0, 0 };
+unsigned char qrecord[] = {5, 'e', 'c', 'h', 'o', 's', 3, 's', 'r', 'v', 0, 0, 1, 0, 1};
+unsigned char arecord[] = {0xc0, 0x0c, 0, 1, 0, 1, 0, 0, 5, 0xbd, 0, 4, 10, 0, 1, 1 };
+
+
+static void after_write(uv_req_t* req, int status) {
+  write_req_t* wr;
+
+  if (status) {
+    uv_err_t err = uv_last_error();
+    fprintf(stderr, "uv_write error: %s\n", uv_strerror(err));
+    ASSERT(0);
+  }
+
+  wr = (write_req_t*) req;
+
+  /* Free the read/write buffer and the request */
+  free(wr->buf.base);
+  free(wr);
+}
+
+
+static void after_shutdown(uv_req_t* req, int status) {
+  uv_close(req->handle, on_close);
+  free(req);
+}
+
+
+static void addrsp(write_req_t* wr, char* hdr) {
+  char * dnsrsp;
+  short int rsplen;
+  short int* reclen;
+
+  rsplen = sizeof(DNSRsp) + sizeof(qrecord) + sizeof(arecord);
+
+  ASSERT (rsplen + wr->buf.len < WRITE_BUF_LEN);
+
+  dnsrsp = wr->buf.base + wr->buf.len;
+
+  /* copy stock response */
+  memcpy(dnsrsp, DNSRsp, sizeof(DNSRsp));
+  memcpy(dnsrsp + sizeof(DNSRsp), qrecord, sizeof(qrecord));
+  memcpy(dnsrsp + sizeof(DNSRsp) + sizeof(qrecord), arecord, sizeof(arecord));
+
+  /* overwrite with network order length and id from request header */
+  reclen = (short int*)dnsrsp;
+  *reclen = htons(rsplen-2);
+  dnsrsp[QUERYID_OFFSET] = hdr[QUERYID_OFFSET];
+  dnsrsp[QUERYID_OFFSET+1] = hdr[QUERYID_OFFSET+1];
+
+  wr->buf.len += rsplen;
+}
+
+static void process_req(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
+  write_req_t *wr;
+  dnshandle* dns = (dnshandle*)handle;
+  char hdrbuf[DNSREC_LEN];
+  int hdrbuf_remaining = DNSREC_LEN;
+  int rec_remaining = 0;
+  int readbuf_remaining;
+  char* dnsreq;
+  char* hdrstart;
+  int usingprev = 0;
+
+  wr = (write_req_t*) malloc(sizeof *wr);
+  uv_req_init(&wr->req, (uv_handle_t*)handle, after_write);
+  wr->buf.base = (char*)malloc(WRITE_BUF_LEN);
+  wr->buf.len = 0;
+
+  if (dns->state.prevbuf_ptr != NULL) {
+    dnsreq = dns->state.prevbuf_ptr + dns->state.prevbuf_pos;
+    readbuf_remaining = dns->state.prevbuf_rem;
+    usingprev = 1;
+  } else {
+    dnsreq = buf.base;
+    readbuf_remaining = nread;
+  }
+  hdrstart = dnsreq;
+
+  while (dnsreq != NULL) {
+    /* something to process */
+    while (readbuf_remaining > 0) {
+      /* something to process in current buffer */
+      if (hdrbuf_remaining > 0) {
+        /* process len and id */
+        if (readbuf_remaining < hdrbuf_remaining) {
+          /* too little to get request header. save for next buffer */
+          memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], dnsreq, readbuf_remaining);
+          hdrbuf_remaining = DNSREC_LEN - readbuf_remaining;
+          break;
+        } else {
+          short int reclen_n;
+          /* save header */
+          memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], dnsreq, hdrbuf_remaining);
+          dnsreq += hdrbuf_remaining;
+          readbuf_remaining -= hdrbuf_remaining;
+          hdrbuf_remaining = 0;
+
+          /* get record length */
+          reclen_n = *((short int*)hdrbuf);
+          rec_remaining = ntohs(reclen_n) - (DNSREC_LEN - 2);
+        }
+      }
+          
+      if (rec_remaining <= readbuf_remaining) {
+        /* prepare reply */
+        addrsp(wr, hdrbuf);
+
+        /* move to next record */
+        dnsreq += rec_remaining;
+        hdrstart = dnsreq;
+        readbuf_remaining -= rec_remaining;
+        rec_remaining = 0;
+        hdrbuf_remaining = DNSREC_LEN;
+      } else {
+        /* otherwise this buffer is done. */
+        rec_remaining -= readbuf_remaining;
+        break;
+      }
+    }
+
+    /* if we had to use bytes from prev buffer, start processing the current one */
+    if (usingprev == 1) {
+      /* free previous buffer */
+      free(dns->state.prevbuf_ptr);
+      dnsreq = buf.base;
+      readbuf_remaining = nread;
+      usingprev = 0;
+    } else {
+      dnsreq = NULL;
+    }
+  }
+
+  /* send write buffer */
+  if (wr->buf.len > 0) {
+    if (uv_write(&wr->req, &wr->buf, 1)) {
+      FATAL("uv_write failed");
+    }
+  }
+
+  if (readbuf_remaining > 0) {
+    /* save start of record position, so we can continue on next read */
+    dns->state.prevbuf_ptr = buf.base;
+    dns->state.prevbuf_pos = hdrstart - buf.base;
+    dns->state.prevbuf_rem = nread - dns->state.prevbuf_pos;
+  } else {
+    /* nothing left in this buffer */
+    dns->state.prevbuf_ptr = NULL;
+    dns->state.prevbuf_pos = 0;
+    dns->state.prevbuf_rem = 0;
+    free(buf.base);
+  }
+}
+
+static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
+  uv_req_t* req;
+
+  if (nread < 0) {
+    /* Error or EOF */
+    ASSERT (uv_last_error().code == UV_EOF);
+
+    if (buf.base) {
+      free(buf.base);
+    }
+
+    req = (uv_req_t*) malloc(sizeof *req);
+    uv_req_init(req, (uv_handle_t*)handle, after_shutdown);
+    uv_shutdown(req);
+
+    return;
+  }
+
+  if (nread == 0) {
+    /* Everything OK, but nothing read. */
+    free(buf.base);
+    return;
+  }
+  /* process requests and send responses */
+  process_req(handle, nread, buf);
+}
+
+
+static void on_close(uv_handle_t* peer) {
+  free(peer);
+}
+
+
+static uv_buf_t buf_alloc(uv_stream_t* handle, size_t suggested_size) {
+  uv_buf_t buf;
+  buf.base = (char*) malloc(suggested_size);
+  buf.len = suggested_size;
+  return buf;
+}
+
+
+static void on_connection(uv_handle_t* server, int status) {
+  dnshandle* handle;
+  int r;
+
+  ASSERT(status == 0);
+
+  handle = (dnshandle*) malloc(sizeof *handle);
+  ASSERT(handle != NULL);
+
+  /* initialize read buffer state */
+  handle->state.prevbuf_ptr = 0;
+  handle->state.prevbuf_pos = 0;
+  handle->state.prevbuf_rem = 0;
+
+  uv_tcp_init((uv_tcp_t*)handle);
+
+  r = uv_accept(server, (uv_stream_t*)handle);
+  ASSERT(r == 0);
+
+  r = uv_read_start((uv_stream_t*)handle, buf_alloc, after_read);
+  ASSERT(r == 0);
+}
+
+
+static void on_server_close(uv_handle_t* handle) {
+  ASSERT(handle == (uv_handle_t*)&server);
+}
+
+
+static int dns_start(int port) {
+  struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port);
+  int r;
+
+  r = uv_tcp_init(&server);
+  if (r) {
+    /* TODO: Error codes */
+    fprintf(stderr, "Socket creation error\n");
+    return 1;
+  }
+
+  r = uv_tcp_bind(&server, addr);
+  if (r) {
+    /* TODO: Error codes */
+    fprintf(stderr, "Bind error\n");
+    return 1;
+  }
+
+  r = uv_tcp_listen(&server, 128, on_connection);
+  if (r) {
+    /* TODO: Error codes */
+    fprintf(stderr, "Listen error\n");
+    return 1;
+  }
+
+  return 0;
+}
+
+
+HELPER_IMPL(dns_server) {
+  uv_init();
+  if (dns_start(TEST_PORT_2))
+    return 1;
+
+  uv_run();
+  return 0;
+}
diff --git a/src/rt/libuv/test/echo-server.c b/src/rt/libuv/test/echo-server.c
index a3f8f29ed10..9addc546c1e 100644
--- a/src/rt/libuv/test/echo-server.c
+++ b/src/rt/libuv/test/echo-server.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -34,12 +34,15 @@ typedef struct {
 static int server_closed;
 static uv_tcp_t server;
 
+static int server6_closed;
+static uv_tcp_t server6;
+
 
 static void after_write(uv_req_t* req, int status);
-static void after_read(uv_tcp_t*, ssize_t nread, uv_buf_t buf);
+static void after_read(uv_stream_t*, ssize_t nread, uv_buf_t buf);
 static void on_close(uv_handle_t* peer);
 static void on_server_close(uv_handle_t* handle);
-static void on_connection(uv_tcp_t*, int status);
+static void on_connection(uv_handle_t*, int status);
 
 
 static void after_write(uv_req_t* req, int status) {
@@ -65,7 +68,7 @@ static void after_shutdown(uv_req_t* req, int status) {
 }
 
 
-static void after_read(uv_tcp_t* handle, ssize_t nread, uv_buf_t buf) {
+static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
   int i;
   write_req_t *wr;
   uv_req_t* req;
@@ -79,7 +82,7 @@ static void after_read(uv_tcp_t* handle, ssize_t nread, uv_buf_t buf) {
     }
 
     req = (uv_req_t*) malloc(sizeof *req);
-    uv_req_init(req, (uv_handle_t*)handle, after_shutdown);
+    uv_req_init(req, (uv_handle_t*)handle, (void *(*)(void *))after_shutdown);
     uv_shutdown(req);
 
     return;
@@ -97,13 +100,15 @@ static void after_read(uv_tcp_t* handle, ssize_t nread, uv_buf_t buf) {
       if (buf.base[i] == 'Q') {
         uv_close((uv_handle_t*)&server, on_server_close);
         server_closed = 1;
+        uv_close((uv_handle_t*)&server6, on_server_close);
+        server6_closed = 1;
       }
     }
   }
 
   wr = (write_req_t*) malloc(sizeof *wr);
 
-  uv_req_init(&wr->req, (uv_handle_t*)handle, after_write);
+  uv_req_init(&wr->req, (uv_handle_t*)handle, (void *(*)(void *))after_write);
   wr->buf.base = buf.base;
   wr->buf.len = nread;
   if (uv_write(&wr->req, &wr->buf, 1)) {
@@ -117,7 +122,7 @@ static void on_close(uv_handle_t* peer) {
 }
 
 
-static uv_buf_t echo_alloc(uv_tcp_t* handle, size_t suggested_size) {
+static uv_buf_t echo_alloc(uv_stream_t* handle, size_t suggested_size) {
   uv_buf_t buf;
   buf.base = (char*) malloc(suggested_size);
   buf.len = suggested_size;
@@ -125,10 +130,13 @@ static uv_buf_t echo_alloc(uv_tcp_t* handle, size_t suggested_size) {
 }
 
 
-static void on_connection(uv_tcp_t* server, int status) {
+static void on_connection(uv_handle_t* server, int status) {
   uv_tcp_t* handle;
   int r;
 
+  if (status != 0) {
+    fprintf(stderr, "Connect error %d\n", uv_last_error().code);
+  }
   ASSERT(status == 0);
 
   handle = (uv_tcp_t*) malloc(sizeof *handle);
@@ -136,21 +144,25 @@ static void on_connection(uv_tcp_t* server, int status) {
 
   uv_tcp_init(handle);
 
-  r = uv_accept(server, handle);
+  /* associate server with stream */
+  handle->data = server;
+
+  r = uv_accept(server, (uv_stream_t*)handle);
   ASSERT(r == 0);
 
-  r = uv_read_start(handle, echo_alloc, after_read);
+  r = uv_read_start((uv_stream_t*)handle, echo_alloc, after_read);
   ASSERT(r == 0);
 }
 
 
 static void on_server_close(uv_handle_t* handle) {
-  ASSERT(handle == (uv_handle_t*)&server);
+  ASSERT(handle == (uv_handle_t*)&server || handle == (uv_handle_t*)&server6);
 }
 
 
 static int echo_start(int port) {
   struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", port);
+  struct sockaddr_in6 addr6 = uv_ip6_addr("::1", port);
   int r;
 
   r = uv_tcp_init(&server);
@@ -160,20 +172,42 @@ static int echo_start(int port) {
     return 1;
   }
 
-  r = uv_bind(&server, addr);
+  r = uv_tcp_bind(&server, addr);
   if (r) {
     /* TODO: Error codes */
     fprintf(stderr, "Bind error\n");
     return 1;
   }
 
-  r = uv_listen(&server, 128, on_connection);
+  r = uv_tcp_listen(&server, 128, on_connection);
   if (r) {
     /* TODO: Error codes */
     fprintf(stderr, "Listen error\n");
     return 1;
   }
 
+  r = uv_tcp_init(&server6);
+  if (r) {
+    /* TODO: Error codes */
+    fprintf(stderr, "Socket creation error\n");
+    return 1;
+  }
+
+  /* IPv6 is optional as not all platforms support it */
+  r = uv_tcp_bind6(&server6, addr6);
+  if (r) {
+    /* show message but return OK */
+    fprintf(stderr, "IPv6 not supported\n");
+    return 0;
+  }
+
+  r = uv_tcp_listen(&server6, 128, on_connection);
+  if (r) {
+    /* TODO: Error codes */
+    fprintf(stderr, "Listen error on IPv6\n");
+    return 1;
+  }
+
   return 0;
 }
 
diff --git a/src/rt/libuv/test/runner-unix.c b/src/rt/libuv/test/runner-unix.c
index 139b671942f..fa4c63bb208 100644
--- a/src/rt/libuv/test/runner-unix.c
+++ b/src/rt/libuv/test/runner-unix.c
@@ -248,7 +248,7 @@ int process_copy_output(process_info_t *p, int fd) {
     return -1;
   }
 
-  size_t nread, nwritten;
+  ssize_t nread, nwritten;
   char buf[1024];
 
   while ((nread = read(fileno(p->stdout_file), buf, 1024)) > 0) {
@@ -331,5 +331,5 @@ int uv_wait_thread(uintptr_t thread_id) {
 
 /* Pause the calling thread for a number of milliseconds. */
 void uv_sleep(int msec) {
-  usleep(msec);
+  usleep(msec * 1000);
 }
diff --git a/src/rt/libuv/test/test-async.c b/src/rt/libuv/test/test-async.c
index d820bf26f60..a9933fdcb14 100644
--- a/src/rt/libuv/test/test-async.c
+++ b/src/rt/libuv/test/test-async.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -118,8 +118,8 @@ static void close_cb(uv_handle_t* handle) {
 }
 
 
-static void async1_cb(uv_handle_t* handle, int status) {
-  ASSERT(handle == (uv_handle_t*)&async1_handle);
+static void async1_cb(uv_async_t* handle, int status) {
+  ASSERT(handle == &async1_handle);
   ASSERT(status == 0);
 
   async1_cb_called++;
@@ -127,7 +127,7 @@ static void async1_cb(uv_handle_t* handle, int status) {
 
   if (async1_cb_called > 2 && !async1_closed) {
     async1_closed = 1;
-    uv_close(handle, close_cb);
+    uv_close((uv_handle_t*)handle, close_cb);
   }
 }
 
@@ -147,10 +147,10 @@ static void async2_cb(uv_handle_t* handle, int status) {
 #endif
 
 
-static void prepare_cb(uv_handle_t* handle, int status) {
+static void prepare_cb(uv_prepare_t* handle, int status) {
   int r;
 
-  ASSERT(handle == (uv_handle_t*)&prepare_handle);
+  ASSERT(handle == &prepare_handle);
   ASSERT(status == 0);
 
   switch (prepare_cb_called) {
@@ -172,7 +172,7 @@ static void prepare_cb(uv_handle_t* handle, int status) {
 #endif
 
     case 1:
-      r = uv_close(handle, close_cb);
+      r = uv_close((uv_handle_t*)handle, close_cb);
       ASSERT(r == 0);
       break;
 
diff --git a/src/rt/libuv/test/test-bind-error.c b/src/rt/libuv/test/test-bind-error.c
index 587224acb92..4ac60654f6d 100644
--- a/src/rt/libuv/test/test-bind-error.c
+++ b/src/rt/libuv/test/test-bind-error.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,17 +43,17 @@ TEST_IMPL(bind_error_addrinuse) {
 
   r = uv_tcp_init(&server1);
   ASSERT(r == 0);
-  r = uv_bind(&server1, addr);
+  r = uv_tcp_bind(&server1, addr);
   ASSERT(r == 0);
 
   r = uv_tcp_init(&server2);
   ASSERT(r == 0);
-  r = uv_bind(&server2, addr);
+  r = uv_tcp_bind(&server2, addr);
   ASSERT(r == 0);
 
-  r = uv_listen(&server1, 128, NULL);
+  r = uv_tcp_listen(&server1, 128, NULL);
   ASSERT(r == 0);
-  r = uv_listen(&server2, 128, NULL);
+  r = uv_tcp_listen(&server2, 128, NULL);
   ASSERT(r == -1);
 
   ASSERT(uv_last_error().code == UV_EADDRINUSE);
@@ -78,7 +78,7 @@ TEST_IMPL(bind_error_addrnotavail_1) {
 
   r = uv_tcp_init(&server);
   ASSERT(r == 0);
-  r = uv_bind(&server, addr);
+  r = uv_tcp_bind(&server, addr);
 
   /* It seems that Linux is broken here - bind succeeds. */
   if (r == -1) {
@@ -104,7 +104,7 @@ TEST_IMPL(bind_error_addrnotavail_2) {
 
   r = uv_tcp_init(&server);
   ASSERT(r == 0);
-  r = uv_bind(&server, addr);
+  r = uv_tcp_bind(&server, addr);
   ASSERT(r == -1);
   ASSERT(uv_last_error().code == UV_EADDRNOTAVAIL);
 
@@ -130,7 +130,7 @@ TEST_IMPL(bind_error_fault) {
 
   r = uv_tcp_init(&server);
   ASSERT(r == 0);
-  r = uv_bind(&server, *garbage_addr);
+  r = uv_tcp_bind(&server, *garbage_addr);
   ASSERT(r == -1);
 
   ASSERT(uv_last_error().code == UV_EFAULT);
@@ -156,9 +156,9 @@ TEST_IMPL(bind_error_inval) {
 
   r = uv_tcp_init(&server);
   ASSERT(r == 0);
-  r = uv_bind(&server, addr1);
+  r = uv_tcp_bind(&server, addr1);
   ASSERT(r == 0);
-  r = uv_bind(&server, addr2);
+  r = uv_tcp_bind(&server, addr2);
   ASSERT(r == -1);
 
   ASSERT(uv_last_error().code == UV_EINVAL);
@@ -171,3 +171,20 @@ TEST_IMPL(bind_error_inval) {
 
   return 0;
 }
+
+
+TEST_IMPL(bind_localhost_ok) {
+  struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT);
+
+  uv_tcp_t server;
+  int r;
+
+  uv_init();
+
+  r = uv_tcp_init(&server);
+  ASSERT(r == 0);
+  r = uv_tcp_bind(&server, addr);
+  ASSERT(r == 0);
+
+  return 0;
+}
diff --git a/src/rt/libuv/test/test-bind6-error.c b/src/rt/libuv/test/test-bind6-error.c
new file mode 100644
index 00000000000..6072dcdc090
--- /dev/null
+++ b/src/rt/libuv/test/test-bind6-error.c
@@ -0,0 +1,164 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+
+static int close_cb_called = 0;
+
+
+static void close_cb(uv_handle_t* handle) {
+  ASSERT(handle != NULL);
+  close_cb_called++;
+}
+
+
+TEST_IMPL(bind6_error_addrinuse) {
+  struct sockaddr_in6 addr = uv_ip6_addr("::", TEST_PORT);
+  uv_tcp_t server1, server2;
+  int r;
+
+  uv_init();
+
+  r = uv_tcp_init(&server1);
+  ASSERT(r == 0);
+  r = uv_tcp_bind6(&server1, addr);
+  ASSERT(r == 0);
+
+  r = uv_tcp_init(&server2);
+  ASSERT(r == 0);
+  r = uv_tcp_bind6(&server2, addr);
+  ASSERT(r == 0);
+
+  r = uv_tcp_listen(&server1, 128, NULL);
+  ASSERT(r == 0);
+  r = uv_tcp_listen(&server2, 128, NULL);
+  ASSERT(r == -1);
+
+  ASSERT(uv_last_error().code == UV_EADDRINUSE);
+
+  uv_close((uv_handle_t*)&server1, close_cb);
+  uv_close((uv_handle_t*)&server2, close_cb);
+
+  uv_run();
+
+  ASSERT(close_cb_called == 2);
+
+  return 0;
+}
+
+
+TEST_IMPL(bind6_error_addrnotavail) {
+  struct sockaddr_in6 addr = uv_ip6_addr("4:4:4:4:4:4:4:4", TEST_PORT);
+  uv_tcp_t server;
+  int r;
+
+  uv_init();
+
+  r = uv_tcp_init(&server);
+  ASSERT(r == 0);
+  r = uv_tcp_bind6(&server, addr);
+  ASSERT(r == -1);
+  ASSERT(uv_last_error().code == UV_EADDRNOTAVAIL);
+
+  uv_close((uv_handle_t*)&server, close_cb);
+
+  uv_run();
+
+  ASSERT(close_cb_called == 1);
+
+  return 0;
+}
+
+
+TEST_IMPL(bind6_error_fault) {
+  char garbage[] = "blah blah blah blah blah blah blah blah blah blah blah blah";
+  struct sockaddr_in6* garbage_addr;
+  uv_tcp_t server;
+  int r;
+
+  garbage_addr = (struct sockaddr_in6*) &garbage;
+
+  uv_init();
+
+  r = uv_tcp_init(&server);
+  ASSERT(r == 0);
+  r = uv_tcp_bind6(&server, *garbage_addr);
+  ASSERT(r == -1);
+
+  ASSERT(uv_last_error().code == UV_EFAULT);
+
+  uv_close((uv_handle_t*)&server, close_cb);
+
+  uv_run();
+
+  ASSERT(close_cb_called == 1);
+
+  return 0;
+}
+
+/* Notes: On Linux uv_bind6(server, NULL) will segfault the program.  */
+
+TEST_IMPL(bind6_error_inval) {
+  struct sockaddr_in6 addr1 = uv_ip6_addr("::", TEST_PORT);
+  struct sockaddr_in6 addr2 = uv_ip6_addr("::", TEST_PORT_2);
+  uv_tcp_t server;
+  int r;
+
+  uv_init();
+
+  r = uv_tcp_init(&server);
+  ASSERT(r == 0);
+  r = uv_tcp_bind6(&server, addr1);
+  ASSERT(r == 0);
+  r = uv_tcp_bind6(&server, addr2);
+  ASSERT(r == -1);
+
+  ASSERT(uv_last_error().code == UV_EINVAL);
+
+  uv_close((uv_handle_t*)&server, close_cb);
+
+  uv_run();
+
+  ASSERT(close_cb_called == 1);
+
+  return 0;
+}
+
+
+TEST_IMPL(bind6_localhost_ok) {
+  struct sockaddr_in6 addr = uv_ip6_addr("::1", TEST_PORT);
+
+  uv_tcp_t server;
+  int r;
+
+  uv_init();
+
+  r = uv_tcp_init(&server);
+  ASSERT(r == 0);
+  r = uv_tcp_bind6(&server, addr);
+  ASSERT(r == 0);
+
+  return 0;
+}
diff --git a/src/rt/libuv/test/test-callback-stack.c b/src/rt/libuv/test/test-callback-stack.c
index 5de5265be68..5b12c8b9b42 100644
--- a/src/rt/libuv/test/test-callback-stack.c
+++ b/src/rt/libuv/test/test-callback-stack.c
@@ -24,7 +24,7 @@
  * stack.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 
 
@@ -43,7 +43,7 @@ static int bytes_received = 0;
 static int shutdown_cb_called = 0;
 
 
-static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
+static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) {
   uv_buf_t buf;
   buf.len = size;
   buf.base = (char*) malloc(size);
@@ -67,10 +67,10 @@ static void shutdown_cb(uv_req_t* req, int status) {
 }
 
 
-static void read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
+static void read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
   ASSERT(nested == 0 && "read_cb must be called from a fresh stack");
 
-  printf("Read. nread == %d\n", nread);
+  printf("Read. nread == %d\n", (int)nread);
   free(buf.base);
 
   if (nread == 0) {
@@ -97,7 +97,7 @@ static void read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
   /* from a fresh stack. */
   if (bytes_received == sizeof MESSAGE) {
     nested++;
-    uv_req_init(&shutdown_req, (uv_handle_t*)tcp, shutdown_cb);
+    uv_req_init(&shutdown_req, (uv_handle_t*)tcp, (void *(*)(void *))shutdown_cb);
 
     puts("Shutdown");
 
@@ -109,24 +109,24 @@ static void read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
 }
 
 
-static void timer_cb(uv_handle_t* handle, int status) {
+static void timer_cb(uv_timer_t* handle, int status) {
   int r;
 
-  ASSERT(handle == (uv_handle_t*)&timer);
+  ASSERT(handle == &timer);
   ASSERT(status == 0);
   ASSERT(nested == 0 && "timer_cb must be called from a fresh stack");
 
   puts("Timeout complete. Now read data...");
 
   nested++;
-  if (uv_read_start(&client, alloc_cb, read_cb)) {
+  if (uv_read_start((uv_stream_t*)&client, alloc_cb, read_cb)) {
     FATAL("uv_read_start failed");
   }
   nested--;
 
   timer_cb_called++;
 
-  r = uv_close(handle, close_cb);
+  r = uv_close((uv_handle_t*)handle, close_cb);
   ASSERT(r == 0);
 }
 
@@ -167,7 +167,7 @@ static void connect_cb(uv_req_t* req, int status) {
   buf.base = (char*) &MESSAGE;
   buf.len = sizeof MESSAGE;
 
-  uv_req_init(&write_req, req->handle, write_cb);
+  uv_req_init(&write_req, req->handle, (void *(*)(void *))write_cb);
 
   if (uv_write(&write_req, &buf, 1)) {
     FATAL("uv_write failed");
@@ -191,9 +191,11 @@ TEST_IMPL(callback_stack) {
   puts("Connecting...");
 
   nested++;
-  uv_req_init(&connect_req, (uv_handle_t*)&client, connect_cb);
-  if (uv_connect(&connect_req, addr)) {
-    FATAL("uv_connect failed");
+  uv_req_init(&connect_req, (uv_handle_t*)&client,
+      (void *(*)(void *))connect_cb);
+
+  if (uv_tcp_connect(&connect_req, addr)) {
+    FATAL("uv_tcp_connect failed");
   }
   nested--;
 
diff --git a/src/rt/libuv/test/test-connection-fail.c b/src/rt/libuv/test/test-connection-fail.c
index fe765197488..9fc3f0ba6eb 100644
--- a/src/rt/libuv/test/test-connection-fail.c
+++ b/src/rt/libuv/test/test-connection-fail.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 
 #include <stdlib.h>
@@ -46,7 +46,7 @@ static void timer_close_cb(uv_handle_t* handle) {
 }
 
 
-static void timer_cb(uv_handle_t* handle, int status) {
+static void timer_cb(uv_timer_t* handle, int status) {
   ASSERT(status == 0);
   timer_cb_calls++;
 
@@ -62,7 +62,7 @@ static void timer_cb(uv_handle_t* handle, int status) {
   uv_close((uv_handle_t*)&tcp, on_close);
 
   /* Close the timer. */
-  uv_close(handle, timer_close_cb);
+  uv_close((uv_handle_t*)handle, timer_close_cb);
 }
 
 
@@ -103,10 +103,10 @@ void connection_fail(uv_connect_cb connect_cb) {
 
   /* We are never doing multiple reads/connects at a time anyway. */
   /* so these handles can be pre-initialized. */
-  uv_req_init(&req, (uv_handle_t*)&tcp, connect_cb);
+  uv_req_init(&req, (uv_handle_t*)&tcp, (void *(*)(void *))connect_cb);
 
-  uv_bind(&tcp, client_addr);
-  r = uv_connect(&req, server_addr);
+  uv_tcp_bind(&tcp, client_addr);
+  r = uv_tcp_connect(&req, server_addr);
   ASSERT(!r);
 
   uv_run();
diff --git a/src/rt/libuv/test/test-delayed-accept.c b/src/rt/libuv/test/test-delayed-accept.c
index f903f9907a5..eabf4818959 100644
--- a/src/rt/libuv/test/test-delayed-accept.c
+++ b/src/rt/libuv/test/test-delayed-accept.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -32,7 +32,7 @@ static int close_cb_called = 0;
 static int connect_cb_called = 0;
 
 
-static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
+static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) {
   uv_buf_t buf;
   buf.base = (char*)malloc(size);
   buf.len = size;
@@ -49,7 +49,7 @@ static void close_cb(uv_handle_t* handle) {
 }
 
 
-static void do_accept(uv_handle_t* timer_handle, int status) {
+static void do_accept(uv_timer_t* timer_handle, int status) {
   uv_tcp_t* server;
   uv_tcp_t* accepted_handle = (uv_tcp_t*)malloc(sizeof *accepted_handle);
   int r;
@@ -65,7 +65,7 @@ static void do_accept(uv_handle_t* timer_handle, int status) {
   tcpcnt = uv_counters()->tcp_init;
 
   server = (uv_tcp_t*)timer_handle->data;
-  r = uv_accept(server, accepted_handle);
+  r = uv_accept((uv_handle_t*)server, (uv_stream_t*)accepted_handle);
   ASSERT(r == 0);
 
   ASSERT(uv_counters()->tcp_init == tcpcnt);
@@ -83,12 +83,12 @@ static void do_accept(uv_handle_t* timer_handle, int status) {
   }
 
   /* Dispose the timer. */
-  r = uv_close(timer_handle, close_cb);
+  r = uv_close((uv_handle_t*)timer_handle, close_cb);
   ASSERT(r == 0);
 }
 
 
-static void connection_cb(uv_tcp_t* tcp, int status) {
+static void connection_cb(uv_handle_t* tcp, int status) {
   int r;
   uv_timer_t* timer_handle;
 
@@ -122,25 +122,30 @@ static void start_server() {
   ASSERT(uv_counters()->tcp_init == 1);
   ASSERT(uv_counters()->handle_init == 1);
 
-  r = uv_bind(server, addr);
+  r = uv_tcp_bind(server, addr);
   ASSERT(r == 0);
 
-  r = uv_listen(server, 128, connection_cb);
+  r = uv_tcp_listen(server, 128, connection_cb);
   ASSERT(r == 0);
 }
 
 
-static void read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
+static void read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
   /* The server will not send anything, it should close gracefully. */
-  ASSERT(tcp != NULL);
-  ASSERT(nread == -1);
-  ASSERT(uv_last_error().code == UV_EOF);
 
   if (buf.base) {
     free(buf.base);
   }
 
-  uv_close((uv_handle_t*)tcp, close_cb);
+  if (nread != -1) {
+    ASSERT(nread == 0);
+    ASSERT(uv_last_error().code == UV_EAGAIN);
+  } else {
+    ASSERT(tcp != NULL);
+    ASSERT(nread == -1);
+    ASSERT(uv_last_error().code == UV_EOF);
+    uv_close((uv_handle_t*)tcp, close_cb);
+  }
 }
 
 
@@ -152,7 +157,7 @@ static void connect_cb(uv_req_t* req, int status) {
 
   /* Not that the server will send anything, but otherwise we'll never know */
   /* when te server closes the connection. */
-  r = uv_read_start((uv_tcp_t*)(req->handle), alloc_cb, read_cb);
+  r = uv_read_start((uv_stream_t*)(req->handle), alloc_cb, read_cb);
   ASSERT(r == 0);
 
   connect_cb_called++;
@@ -173,8 +178,8 @@ static void client_connect() {
   r = uv_tcp_init(client);
   ASSERT(r == 0);
 
-  uv_req_init(connect_req, (uv_handle_t*)client, connect_cb);
-  r = uv_connect(connect_req, addr);
+  uv_req_init(connect_req, (uv_handle_t*)client, (void *(*)(void *))connect_cb);
+  r = uv_tcp_connect(connect_req, addr);
   ASSERT(r == 0);
 }
 
diff --git a/src/rt/libuv/test/test-get-currentexe.c b/src/rt/libuv/test/test-get-currentexe.c
index 880d9cd6d0f..1dc85565590 100644
--- a/src/rt/libuv/test/test-get-currentexe.c
+++ b/src/rt/libuv/test/test-get-currentexe.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 #include <string.h>
 
@@ -33,20 +33,20 @@ TEST_IMPL(get_currentexe) {
   int r;
 
   size = sizeof(buffer) / sizeof(buffer[0]);
-  r = uv_get_exepath(buffer, &size);
+  r = uv_exepath(buffer, &size);
   ASSERT(!r);
 
   match = strstr(buffer, executable_path);
-  /* Verify that the path returned from uv_get_exepath is a subdirectory of executable_path */
+  /* Verify that the path returned from uv_exepath is a subdirectory of executable_path */
   ASSERT(match && !strcmp(match, executable_path));
   ASSERT(size == strlen(buffer));
 
   /* Negative tests */
   size = sizeof(buffer) / sizeof(buffer[0]);
-  r = uv_get_exepath(NULL, &size);
+  r = uv_exepath(NULL, &size);
   ASSERT(r == -1);
 
-  r = uv_get_exepath(buffer, NULL);
+  r = uv_exepath(buffer, NULL);
   ASSERT(r == -1);
 
   return 0;
diff --git a/src/rt/libuv/test/test-getaddrinfo.c b/src/rt/libuv/test/test-getaddrinfo.c
new file mode 100644
index 00000000000..a33e3d075cc
--- /dev/null
+++ b/src/rt/libuv/test/test-getaddrinfo.c
@@ -0,0 +1,110 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h> /* strlen */
+
+
+#define CONCURRENT_COUNT    10
+
+static const char* name = "localhost";
+
+static uv_getaddrinfo_t getaddrinfo_handle;
+static int getaddrinfo_cbs = 0;
+
+/* data used for running multiple calls concurrently */
+static uv_getaddrinfo_t getaddrinfo_handles[CONCURRENT_COUNT];
+static int callback_counts[CONCURRENT_COUNT];
+
+
+static void getaddrinfo_basic_cb(uv_getaddrinfo_t* handle,
+                                 int status,
+                                 struct addrinfo* res) {
+  ASSERT(handle == &getaddrinfo_handle);
+  getaddrinfo_cbs++;
+}
+
+
+static void getaddrinfo_cuncurrent_cb(uv_getaddrinfo_t* handle,
+                                      int status,
+                                      struct addrinfo* res) {
+  int i;
+
+  for (i = 0; i < CONCURRENT_COUNT; i++) {
+    if (&getaddrinfo_handles[i] == handle) {
+      callback_counts[i]++;
+      break;
+    }
+  }
+  ASSERT (i < CONCURRENT_COUNT);
+
+  getaddrinfo_cbs++;
+}
+
+
+TEST_IMPL(getaddrinfo_basic) {
+  int r;
+
+  uv_init();
+
+  r = uv_getaddrinfo(&getaddrinfo_handle,
+                     &getaddrinfo_basic_cb,
+                     name,
+                     NULL,
+                     NULL);
+  ASSERT(r == 0);
+
+  uv_run();
+
+  ASSERT(getaddrinfo_cbs == 1);
+
+  return 0;
+}
+
+
+TEST_IMPL(getaddrinfo_concurrent) {
+  int i, r;
+
+  uv_init();
+
+  for (i = 0; i < CONCURRENT_COUNT; i++) {
+    callback_counts[i] = 0;
+
+    r = uv_getaddrinfo(&getaddrinfo_handles[i],
+                   &getaddrinfo_cuncurrent_cb,
+                   name,
+                   NULL,
+                   NULL);
+    ASSERT(r == 0);
+  }
+
+  uv_run();
+
+  for (i = 0; i < CONCURRENT_COUNT; i++) {
+    ASSERT(callback_counts[i] == 1);
+  }
+
+  return 0;
+}
diff --git a/src/rt/libuv/test/test-gethostbyname.c b/src/rt/libuv/test/test-gethostbyname.c
new file mode 100644
index 00000000000..cbd25343bbb
--- /dev/null
+++ b/src/rt/libuv/test/test-gethostbyname.c
@@ -0,0 +1,192 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h> /* strlen */
+
+ares_channel channel;
+struct ares_options options;
+int optmask;
+
+int ares_bynamecallbacks;
+int bynamecallbacksig;
+int ares_byaddrcallbacks;
+int byaddrcallbacksig;
+
+static void aresbynamecallback( void *arg,
+                          int status,
+                          int timeouts,
+                          struct hostent *hostent) {
+  int * iargs;
+  ASSERT(arg != NULL);
+  iargs = (int*)arg;
+  ASSERT(*iargs == bynamecallbacksig);
+  ASSERT(timeouts == 0);
+
+  printf("aresbynamecallback %d\n", ares_bynamecallbacks++);
+}
+
+
+static void aresbyaddrcallback( void *arg,
+                          int status,
+                          int timeouts,
+                          struct hostent *hostent) {
+  int * iargs;
+  ASSERT(arg != NULL);
+  iargs = (int*)arg;
+  ASSERT(*iargs == byaddrcallbacksig);
+  ASSERT(timeouts == 0);
+
+  printf("aresbyaddrcallback %d\n", ares_byaddrcallbacks++);
+}
+
+
+static void prep_tcploopback() {
+  /* for test, use echo server - TCP port TEST_PORT on loopback */
+  struct sockaddr_in test_server = uv_ip4_addr("127.0.0.1", 0);
+  int rc;
+
+  optmask = ARES_OPT_SERVERS | ARES_OPT_TCP_PORT | ARES_OPT_FLAGS;
+  options.servers = &test_server.sin_addr;
+  options.nservers = 1;
+  options.tcp_port = htons(TEST_PORT);
+  options.flags = ARES_FLAG_USEVC;
+
+  rc = uv_ares_init_options(&channel, &options, optmask);
+
+  ASSERT(rc == ARES_SUCCESS);
+}
+
+
+TEST_IMPL(gethostbyname) {
+
+  int rc = 0;
+  char addr[4];
+
+  rc = ares_library_init(ARES_LIB_INIT_ALL);
+  if (rc != 0) {
+    printf("ares library init fails %d\n", rc);
+    return 1;
+  }
+
+  uv_init();
+
+  printf("Start basic gethostbyname test\n");
+  prep_tcploopback();
+
+  ares_bynamecallbacks = 0;
+  bynamecallbacksig = 7;
+
+  ares_gethostbyname(channel,
+                    "microsoft.com",
+                    AF_INET,
+                    &aresbynamecallback,
+                    &bynamecallbacksig);
+  uv_run();
+
+  ASSERT(ares_bynamecallbacks == 1);
+
+  uv_ares_destroy(channel);
+  printf("Done basic gethostbyname test\n");
+
+
+  /* two sequential call on new channel */
+
+  printf("Start gethostbyname and gethostbyaddr sequential test\n");
+  prep_tcploopback();
+
+  ares_bynamecallbacks = 0;
+  bynamecallbacksig = 7;
+
+  ares_gethostbyname(channel,
+                    "microsoft.com",
+                    AF_INET,
+                    &aresbynamecallback,
+                    &bynamecallbacksig);
+  uv_run();
+
+  ASSERT(ares_bynamecallbacks == 1);
+
+  ares_byaddrcallbacks = 0;
+  byaddrcallbacksig = 8;
+  addr[0] = 10;
+  addr[1] = 0;
+  addr[2] = 1;
+  addr[3] = 99;
+
+  ares_gethostbyaddr(channel,
+                    addr,
+                    4,
+                    AF_INET,
+                    &aresbyaddrcallback,
+                    &byaddrcallbacksig);
+
+  uv_run();
+
+  ASSERT(ares_byaddrcallbacks == 1);
+
+  uv_ares_destroy(channel);
+  printf("Done gethostbyname and gethostbyaddr sequential test\n");
+
+
+  /* two simultaneous calls on new channel */
+
+  printf("Start gethostbyname and gethostbyaddr concurrent test\n");
+  prep_tcploopback();
+
+  ares_bynamecallbacks = 0;
+  bynamecallbacksig = 7;
+
+  ares_gethostbyname(channel,
+                    "microsoft.com",
+                    AF_INET,
+                    &aresbynamecallback,
+                    &bynamecallbacksig);
+
+  ares_byaddrcallbacks = 0;
+  byaddrcallbacksig = 8;
+  addr[0] = 10;
+  addr[1] = 0;
+  addr[2] = 1;
+  addr[3] = 99;
+
+  ares_gethostbyaddr(channel,
+                    addr,
+                    4,
+                    AF_INET,
+                    &aresbyaddrcallback,
+                    &byaddrcallbacksig);
+
+  uv_run();
+
+  ASSERT(ares_bynamecallbacks == 1);
+  ASSERT(ares_byaddrcallbacks == 1);
+
+
+  uv_ares_destroy(channel);
+  printf("Done gethostbyname and gethostbyaddr concurrent test\n");
+
+  return 0;
+}
diff --git a/src/rt/libuv/test/test-hrtime.c b/src/rt/libuv/test/test-hrtime.c
new file mode 100644
index 00000000000..4d96e3331ec
--- /dev/null
+++ b/src/rt/libuv/test/test-hrtime.c
@@ -0,0 +1,54 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "uv.h"
+#include "task.h"
+
+
+#ifndef MICROSEC
+# define MICROSEC 1000000
+#endif
+
+#ifndef NANOSEC
+# define NANOSEC 1000000000
+#endif
+
+
+
+/*
+ * We expect the amount of time passed to be at least one us plus two system
+ * calls. Therefore checking that at least a microsecond has elapsed is safe.
+ */
+TEST_IMPL(hrtime) {
+  uint64_t a, b, diff;
+
+  a = uv_hrtime();
+  uv_sleep(100);
+  b = uv_hrtime();
+
+  diff = b - a;
+
+  printf("diff = %llu\n", diff);
+
+  ASSERT(diff >= NANOSEC / MICROSEC);
+  ASSERT(diff > MICROSEC);
+  return 0;
+}
diff --git a/src/rt/libuv/test/test-list.h b/src/rt/libuv/test/test-list.h
index c3cb2522468..190574acaa8 100644
--- a/src/rt/libuv/test/test-list.h
+++ b/src/rt/libuv/test/test-list.h
@@ -20,6 +20,7 @@
  */
 
 TEST_DECLARE   (ping_pong)
+TEST_DECLARE   (ping_pong_v6)
 TEST_DECLARE   (delayed_accept)
 TEST_DECLARE   (tcp_writealot)
 TEST_DECLARE   (bind_error_addrinuse)
@@ -27,6 +28,12 @@ TEST_DECLARE   (bind_error_addrnotavail_1)
 TEST_DECLARE   (bind_error_addrnotavail_2)
 TEST_DECLARE   (bind_error_fault)
 TEST_DECLARE   (bind_error_inval)
+TEST_DECLARE   (bind_localhost_ok)
+TEST_DECLARE   (bind6_error_addrinuse)
+TEST_DECLARE   (bind6_error_addrnotavail)
+TEST_DECLARE   (bind6_error_fault)
+TEST_DECLARE   (bind6_error_inval)
+TEST_DECLARE   (bind6_localhost_ok)
 TEST_DECLARE   (connection_fail)
 TEST_DECLARE   (connection_fail_doesnt_auto_close)
 TEST_DECLARE   (shutdown_eof)
@@ -41,28 +48,39 @@ TEST_DECLARE   (prepare_ref)
 TEST_DECLARE   (check_ref)
 TEST_DECLARE   (async)
 TEST_DECLARE   (get_currentexe)
+TEST_DECLARE   (hrtime)
+TEST_DECLARE   (getaddrinfo_basic)
+TEST_DECLARE   (getaddrinfo_concurrent)
+TEST_DECLARE   (gethostbyname)
 TEST_DECLARE   (fail_always)
 TEST_DECLARE   (pass_always)
 HELPER_DECLARE (echo_server)
 
+
 TASK_LIST_START
   TEST_ENTRY  (ping_pong)
   TEST_HELPER (ping_pong, echo_server)
 
+  TEST_ENTRY  (ping_pong_v6)
+  TEST_HELPER (ping_pong_v6, echo_server)
+
   TEST_ENTRY  (delayed_accept)
 
   TEST_ENTRY  (tcp_writealot)
   TEST_HELPER (tcp_writealot, echo_server)
 
   TEST_ENTRY  (bind_error_addrinuse)
-
   TEST_ENTRY  (bind_error_addrnotavail_1)
-
   TEST_ENTRY  (bind_error_addrnotavail_2)
-
   TEST_ENTRY  (bind_error_fault)
-
   TEST_ENTRY  (bind_error_inval)
+  TEST_ENTRY  (bind_localhost_ok)
+
+  TEST_ENTRY  (bind6_error_addrinuse)
+  TEST_ENTRY  (bind6_error_addrnotavail)
+  TEST_ENTRY  (bind6_error_fault)
+  TEST_ENTRY  (bind6_error_inval)
+  TEST_ENTRY  (bind6_localhost_ok)
 
   TEST_ENTRY  (connection_fail)
   TEST_ENTRY  (connection_fail_doesnt_auto_close)
@@ -89,6 +107,14 @@ TASK_LIST_START
 
   TEST_ENTRY  (get_currentexe)
 
+  TEST_ENTRY  (hrtime)
+
+  TEST_ENTRY  (getaddrinfo_basic)
+  TEST_ENTRY  (getaddrinfo_concurrent)
+
+  TEST_ENTRY  (gethostbyname)
+  TEST_HELPER (gethostbyname, echo_server)
+
 #if 0
   /* These are for testing the test runner. */
   TEST_ENTRY  (fail_always)
diff --git a/src/rt/libuv/test/test-loop-handles.c b/src/rt/libuv/test/test-loop-handles.c
index fa9cc18cc55..7979a74b4ae 100644
--- a/src/rt/libuv/test/test-loop-handles.c
+++ b/src/rt/libuv/test/test-loop-handles.c
@@ -64,7 +64,7 @@
  */
 
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 
 #include <math.h>
@@ -109,8 +109,8 @@ static int idle_2_is_active = 0;
 static int timer_cb_called = 0;
 
 
-static void timer_cb(uv_handle_t* handle, int status) {
-  ASSERT(handle == (uv_handle_t*)&timer_handle);
+static void timer_cb(uv_timer_t* handle, int status) {
+  ASSERT(handle == &timer_handle);
   ASSERT(status == 0);
 
   timer_cb_called++;
@@ -129,22 +129,22 @@ static void idle_2_close_cb(uv_handle_t* handle) {
 }
 
 
-static void idle_2_cb(uv_handle_t* handle, int status) {
+static void idle_2_cb(uv_idle_t* handle, int status) {
   int r;
 
   LOG("IDLE_2_CB\n");
 
-  ASSERT(handle == (uv_handle_t*)&idle_2_handle);
+  ASSERT(handle == &idle_2_handle);
   ASSERT(status == 0);
 
   idle_2_cb_called++;
 
-  r = uv_close(handle, idle_2_close_cb);
+  r = uv_close((uv_handle_t*)handle, idle_2_close_cb);
   ASSERT(r == 0);
 }
 
 
-static void idle_1_cb(uv_handle_t* handle, int status) {
+static void idle_1_cb(uv_idle_t* handle, int status) {
   int r;
 
   LOG("IDLE_1_CB\n");
@@ -207,12 +207,12 @@ static void prepare_2_close_cb(uv_handle_t* handle) {
 }
 
 
-static void check_cb(uv_handle_t* handle, int status) {
+static void check_cb(uv_check_t* handle, int status) {
   int i, r;
 
   LOG("CHECK_CB\n");
 
-  ASSERT(handle == (uv_handle_t*)&check_handle);
+  ASSERT(handle == &check_handle);
   ASSERT(status == 0);
 
   /* XXX
@@ -254,12 +254,12 @@ static void check_cb(uv_handle_t* handle, int status) {
 }
 
 
-static void prepare_2_cb(uv_handle_t* handle, int status) {
+static void prepare_2_cb(uv_prepare_t* handle, int status) {
   int r;
 
   LOG("PREPARE_2_CB\n");
 
-  ASSERT(handle == (uv_handle_t*)&prepare_2_handle);
+  ASSERT(handle == &prepare_2_handle);
   ASSERT(status == 0);
 
   /* XXX ASSERT(idles_1_active == 0); */
@@ -278,12 +278,12 @@ static void prepare_2_cb(uv_handle_t* handle, int status) {
 }
 
 
-static void prepare_1_cb(uv_handle_t* handle, int status) {
+static void prepare_1_cb(uv_prepare_t* handle, int status) {
   int r;
 
   LOG("PREPARE_1_CB\n");
 
-  ASSERT(handle == (uv_handle_t*)&prepare_1_handle);
+  ASSERT(handle == &prepare_1_handle);
   ASSERT(status == 0);
 
   /* XXX
diff --git a/src/rt/libuv/test/test-ping-pong.c b/src/rt/libuv/test/test-ping-pong.c
index d8bf13d1f0e..34de78b5b6c 100644
--- a/src/rt/libuv/test/test-ping-pong.c
+++ b/src/rt/libuv/test/test-ping-pong.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 
 #include <stdlib.h>
@@ -48,7 +48,7 @@ typedef struct {
 void pinger_try_read(pinger_t* pinger);
 
 
-static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
+static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) {
   uv_buf_t buf;
   buf.base = (char*)malloc(size);
   buf.len = size;
@@ -82,7 +82,8 @@ static void pinger_write_ping(pinger_t* pinger) {
   buf.len = strlen(PING);
 
   req = (uv_req_t*)malloc(sizeof(*req));
-  uv_req_init(req, (uv_handle_t*)(&pinger->tcp), pinger_after_write);
+  uv_req_init(req, (uv_handle_t*)(&pinger->tcp),
+      (void *(*)(void *))pinger_after_write);
 
   if (uv_write(req, &buf, 1)) {
     FATAL("uv_write failed");
@@ -92,7 +93,7 @@ static void pinger_write_ping(pinger_t* pinger) {
 }
 
 
-static void pinger_read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
+static void pinger_read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
   unsigned int i;
   pinger_t* pinger;
 
@@ -137,7 +138,7 @@ static void pinger_on_connect(uv_req_t *req, int status) {
 
   pinger_write_ping(pinger);
 
-  uv_read_start((uv_tcp_t*)(req->handle), alloc_cb, pinger_read_cb);
+  uv_read_start((uv_stream_t*)(req->handle), alloc_cb, pinger_read_cb);
 }
 
 
@@ -158,9 +159,9 @@ static void pinger_new() {
   /* We are never doing multiple reads/connects at a time anyway. */
   /* so these handles can be pre-initialized. */
   uv_req_init(&pinger->connect_req, (uv_handle_t*)(&pinger->tcp),
-      pinger_on_connect);
+      (void *(*)(void *))pinger_on_connect);
 
-  r = uv_connect(&pinger->connect_req, server_addr);
+  r = uv_tcp_connect(&pinger->connect_req, server_addr);
   ASSERT(!r);
 }
 
@@ -175,3 +176,40 @@ TEST_IMPL(ping_pong) {
 
   return 0;
 }
+
+
+/* same ping-pong test, but using IPv6 connection */
+static void pinger_v6_new() {
+  int r;
+  struct sockaddr_in6 server_addr = uv_ip6_addr("::1", TEST_PORT);
+  pinger_t *pinger;
+
+  pinger = (pinger_t*)malloc(sizeof(*pinger));
+  pinger->state = 0;
+  pinger->pongs = 0;
+
+  /* Try to connec to the server and do NUM_PINGS ping-pongs. */
+  r = uv_tcp_init(&pinger->tcp);
+  pinger->tcp.data = pinger;
+  ASSERT(!r);
+
+  /* We are never doing multiple reads/connects at a time anyway. */
+  /* so these handles can be pre-initialized. */
+  uv_req_init(&pinger->connect_req, (uv_handle_t*)(&pinger->tcp),
+      (void *(*)(void *))pinger_on_connect);
+
+  r = uv_tcp_connect6(&pinger->connect_req, server_addr);
+  ASSERT(!r);
+}
+
+
+TEST_IMPL(ping_pong_v6) {
+  uv_init();
+
+  pinger_v6_new();
+  uv_run();
+
+  ASSERT(completed_pingers == 1);
+
+  return 0;
+}
diff --git a/src/rt/libuv/test/test-shutdown-eof.c b/src/rt/libuv/test/test-shutdown-eof.c
index 1ce81f71be7..8a960c9ea6a 100644
--- a/src/rt/libuv/test/test-shutdown-eof.c
+++ b/src/rt/libuv/test/test-shutdown-eof.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,7 +37,7 @@ static int called_timer_close_cb;
 static int called_timer_cb;
 
 
-static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
+static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) {
   uv_buf_t buf;
   buf.base = (char*)malloc(size);
   buf.len = size;
@@ -45,8 +45,16 @@ static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
 }
 
 
-static void read_cb(uv_tcp_t* t, ssize_t nread, uv_buf_t buf) {
-  ASSERT(t == &tcp);
+static void read_cb(uv_stream_t* t, ssize_t nread, uv_buf_t buf) {
+  uv_err_t err = uv_last_error();
+
+  ASSERT((uv_tcp_t*)t == &tcp);
+
+  if (nread == 0) {
+    ASSERT(err.code == UV_EAGAIN);
+    free(buf.base);
+    return;
+  }
 
   if (!got_q) {
     ASSERT(nread == 1);
@@ -56,7 +64,7 @@ static void read_cb(uv_tcp_t* t, ssize_t nread, uv_buf_t buf) {
     got_q = 1;
     puts("got Q");
   } else {
-    ASSERT(uv_last_error().code == UV_EOF);
+    ASSERT(err.code == UV_EOF);
     if (buf.base) {
       free(buf.base);
     }
@@ -84,7 +92,7 @@ static void connect_cb(uv_req_t *req, int status) {
   ASSERT(req == &connect_req);
 
   /* Start reading from our connection so we can receive the EOF.  */
-  uv_read_start(&tcp, alloc_cb, read_cb);
+  uv_read_start((uv_stream_t*)&tcp, alloc_cb, read_cb);
 
   /*
    * Write the letter 'Q' to gracefully kill the echo-server. This will not
@@ -94,7 +102,7 @@ static void connect_cb(uv_req_t *req, int status) {
   uv_write(&write_req, &qbuf, 1);
 
   /* Shutdown our end of the connection.  */
-  uv_req_init(&shutdown_req, (uv_handle_t*)&tcp, shutdown_cb);
+  uv_req_init(&shutdown_req, (uv_handle_t*)&tcp, (void *(*)(void *))shutdown_cb);
   uv_shutdown(&shutdown_req);
 
   called_connect_cb++;
@@ -120,9 +128,9 @@ void timer_close_cb(uv_handle_t* handle) {
 }
 
 
-void timer_cb(uv_handle_t* handle, int status) {
-  ASSERT(handle == (uv_handle_t*) &timer);
-  uv_close(handle, timer_close_cb);
+void timer_cb(uv_timer_t* handle, int status) {
+  ASSERT(handle == &timer);
+  uv_close((uv_handle_t*) handle, timer_close_cb);
 
   /*
    * The most important assert of the test: we have not received
@@ -157,8 +165,8 @@ TEST_IMPL(shutdown_eof) {
   r = uv_tcp_init(&tcp);
   ASSERT(!r);
 
-  uv_req_init(&connect_req, (uv_handle_t*) &tcp, connect_cb);
-  r = uv_connect(&connect_req, server_addr);
+  uv_req_init(&connect_req, (uv_handle_t*) &tcp, (void *(*)(void *))connect_cb);
+  r = uv_tcp_connect(&connect_req, server_addr);
   ASSERT(!r);
 
   uv_run();
diff --git a/src/rt/libuv/test/test-tcp-writealot.c b/src/rt/libuv/test/test-tcp-writealot.c
index 5105a0477aa..4e305a9f33d 100644
--- a/src/rt/libuv/test/test-tcp-writealot.c
+++ b/src/rt/libuv/test/test-tcp-writealot.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 #include <stdio.h>
 #include <stdlib.h>
@@ -45,7 +45,7 @@ static int bytes_received = 0;
 static int bytes_received_done = 0;
 
 
-static uv_buf_t alloc_cb(uv_tcp_t* tcp, size_t size) {
+static uv_buf_t alloc_cb(uv_stream_t* tcp, size_t size) {
   uv_buf_t buf;
   buf.base = (char*)malloc(size);
   buf.len = size;
@@ -83,7 +83,7 @@ static void shutdown_cb(uv_req_t* req, int status) {
 }
 
 
-static void read_cb(uv_tcp_t* tcp, ssize_t nread, uv_buf_t buf) {
+static void read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) {
   ASSERT(tcp != NULL);
 
   if (nread < 0) {
@@ -144,7 +144,7 @@ static void connect_cb(uv_req_t* req, int status) {
     req = (uv_req_t*)malloc(sizeof *req);
     ASSERT(req != NULL);
 
-    uv_req_init(req, (uv_handle_t*)tcp, write_cb);
+    uv_req_init(req, (uv_handle_t*)tcp, (void *(*)(void *))write_cb);
     r = uv_write(req, (uv_buf_t*)&send_bufs, CHUNKS_PER_WRITE);
     ASSERT(r == 0);
   }
@@ -152,7 +152,7 @@ static void connect_cb(uv_req_t* req, int status) {
   /* Shutdown on drain. FIXME: dealloc req? */
   req = (uv_req_t*) malloc(sizeof(uv_req_t));
   ASSERT(req != NULL);
-  uv_req_init(req, (uv_handle_t*)tcp, shutdown_cb);
+  uv_req_init(req, (uv_handle_t*)tcp, (void *(*)(void *))shutdown_cb);
   r = uv_shutdown(req);
   ASSERT(r == 0);
 
@@ -160,8 +160,8 @@ static void connect_cb(uv_req_t* req, int status) {
   req = (uv_req_t*)malloc(sizeof *req);
   ASSERT(req != NULL);
 
-  uv_req_init(req, (uv_handle_t*)tcp, read_cb);
-  r = uv_read_start(tcp, alloc_cb, read_cb);
+  uv_req_init(req, (uv_handle_t*)tcp, (void *(*)(void *))read_cb);
+  r = uv_read_start((uv_stream_t*)tcp, alloc_cb, read_cb);
   ASSERT(r == 0);
 }
 
@@ -184,8 +184,8 @@ TEST_IMPL(tcp_writealot) {
   r = uv_tcp_init(client);
   ASSERT(r == 0);
 
-  uv_req_init(connect_req, (uv_handle_t*)client, connect_cb);
-  r = uv_connect(connect_req, addr);
+  uv_req_init(connect_req, (uv_handle_t*)client, (void *(*)(void *))connect_cb);
+  r = uv_tcp_connect(connect_req, addr);
   ASSERT(r == 0);
 
   uv_run();
diff --git a/src/rt/libuv/test/test-timer-again.c b/src/rt/libuv/test/test-timer-again.c
index 77482083491..e083b01ced1 100644
--- a/src/rt/libuv/test/test-timer-again.c
+++ b/src/rt/libuv/test/test-timer-again.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 
 
@@ -41,10 +41,10 @@ static void close_cb(uv_handle_t* handle) {
 }
 
 
-static void repeat_1_cb(uv_handle_t* handle, int status) {
+static void repeat_1_cb(uv_timer_t* handle, int status) {
   int r;
 
-  ASSERT(handle == (uv_handle_t*)&repeat_1);
+  ASSERT(handle == &repeat_1);
   ASSERT(status == 0);
 
   ASSERT(uv_timer_get_repeat((uv_timer_t*)handle) == 50);
@@ -57,7 +57,7 @@ static void repeat_1_cb(uv_handle_t* handle, int status) {
   ASSERT(r == 0);
 
   if (uv_now() >= start_time + 500) {
-    uv_close(handle, close_cb);
+    uv_close((uv_handle_t*)handle, close_cb);
     /* We're not calling uv_timer_again on repeat_2 any more, so after this */
     /* timer_2_cb is expected. */
     repeat_2_cb_allowed = 1;
@@ -66,8 +66,8 @@ static void repeat_1_cb(uv_handle_t* handle, int status) {
 }
 
 
-static void repeat_2_cb(uv_handle_t* handle, int status) {
-  ASSERT(handle == (uv_handle_t*) &repeat_2);
+static void repeat_2_cb(uv_timer_t* handle, int status) {
+  ASSERT(handle == &repeat_2);
   ASSERT(status == 0);
   ASSERT(repeat_2_cb_allowed);
 
@@ -76,8 +76,8 @@ static void repeat_2_cb(uv_handle_t* handle, int status) {
   repeat_2_cb_called++;
 
   if (uv_timer_get_repeat(&repeat_2) == 0) {
-    ASSERT(!uv_is_active(handle));
-    uv_close(handle, close_cb);
+    ASSERT(!uv_is_active((uv_handle_t*)handle));
+    uv_close((uv_handle_t*)handle, close_cb);
     return;
   }
 
diff --git a/src/rt/libuv/test/test-timer.c b/src/rt/libuv/test/test-timer.c
index 5d39ad717c2..c62a8c68dbc 100644
--- a/src/rt/libuv/test/test-timer.c
+++ b/src/rt/libuv/test/test-timer.c
@@ -19,7 +19,7 @@
  * IN THE SOFTWARE.
  */
 
-#include "../uv.h"
+#include "uv.h"
 #include "task.h"
 
 
@@ -42,7 +42,7 @@ static void once_close_cb(uv_handle_t* handle) {
 }
 
 
-static void once_cb(uv_handle_t* handle, int status) {
+static void once_cb(uv_timer_t* handle, int status) {
   printf("ONCE_CB %d\n", once_cb_called);
 
   ASSERT(handle != NULL);
@@ -50,7 +50,7 @@ static void once_cb(uv_handle_t* handle, int status) {
 
   once_cb_called++;
 
-  uv_close(handle, once_close_cb);
+  uv_close((uv_handle_t*)handle, once_close_cb);
 
   /* Just call this randomly for the code coverage. */
   uv_update_time();
@@ -66,7 +66,7 @@ static void repeat_close_cb(uv_handle_t* handle) {
 }
 
 
-static void repeat_cb(uv_handle_t* handle, int status) {
+static void repeat_cb(uv_timer_t* handle, int status) {
   printf("REPEAT_CB\n");
 
   ASSERT(handle != NULL);
@@ -75,12 +75,12 @@ static void repeat_cb(uv_handle_t* handle, int status) {
   repeat_cb_called++;
 
   if (repeat_cb_called == 5) {
-    uv_close(handle, repeat_close_cb);
+    uv_close((uv_handle_t*)handle, repeat_close_cb);
   }
 }
 
 
-static void never_cb(uv_handle_t* handle, int status) {
+static void never_cb(uv_timer_t* handle, int status) {
   FATAL("never_cb should never be called");
 }