Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / system / core_unittest.cc
index af3d0c1..8d1441c 100644 (file)
@@ -4,9 +4,10 @@
 
 #include "mojo/system/core.h"
 
+#include <stdint.h>
+
 #include <limits>
 
-#include "base/basictypes.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
 #include "mojo/system/core_test_base.h"
@@ -15,6 +16,9 @@ namespace mojo {
 namespace system {
 namespace {
 
+const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u};
+const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u};
+
 typedef test::CoreTestBase CoreTest;
 
 TEST_F(CoreTest, GetTimeTicksNow) {
@@ -38,75 +42,143 @@ TEST_F(CoreTest, Basic) {
 
   EXPECT_EQ(0u, info.GetWriteMessageCallCount());
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->WriteMessage(h, NULL, 0, NULL, 0,
+            core()->WriteMessage(h,
+                                 NullUserPointer(),
+                                 0,
+                                 NullUserPointer(),
+                                 0,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
   EXPECT_EQ(1u, info.GetWriteMessageCallCount());
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            core()->WriteMessage(h, NULL, 1, NULL, 0,
-                                 MOJO_WRITE_MESSAGE_FLAG_NONE));
-  EXPECT_EQ(2u, info.GetWriteMessageCallCount());
 
   EXPECT_EQ(0u, info.GetReadMessageCallCount());
   uint32_t num_bytes = 0;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->ReadMessage(h, NULL, &num_bytes, NULL, NULL,
+            core()->ReadMessage(h,
+                                NullUserPointer(),
+                                MakeUserPointer(&num_bytes),
+                                NullUserPointer(),
+                                NullUserPointer(),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(1u, info.GetReadMessageCallCount());
-  num_bytes = 1;
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            core()->ReadMessage(h, NULL, &num_bytes, NULL, NULL,
-                                MOJO_READ_MESSAGE_FLAG_NONE));
-  EXPECT_EQ(2u, info.GetReadMessageCallCount());
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->ReadMessage(h, NULL, NULL, NULL, NULL,
+            core()->ReadMessage(h,
+                                NullUserPointer(),
+                                NullUserPointer(),
+                                NullUserPointer(),
+                                NullUserPointer(),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
-  EXPECT_EQ(3u, info.GetReadMessageCallCount());
+  EXPECT_EQ(2u, info.GetReadMessageCallCount());
 
   EXPECT_EQ(0u, info.GetWriteDataCallCount());
-  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
-            core()->WriteData(h, NULL, NULL, MOJO_WRITE_DATA_FLAG_NONE));
+  EXPECT_EQ(
+      MOJO_RESULT_UNIMPLEMENTED,
+      core()->WriteData(
+          h, NullUserPointer(), NullUserPointer(), MOJO_WRITE_DATA_FLAG_NONE));
   EXPECT_EQ(1u, info.GetWriteDataCallCount());
 
   EXPECT_EQ(0u, info.GetBeginWriteDataCallCount());
-  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
-            core()->BeginWriteData(h, NULL, NULL, MOJO_WRITE_DATA_FLAG_NONE));
+  EXPECT_EQ(
+      MOJO_RESULT_UNIMPLEMENTED,
+      core()->BeginWriteData(
+          h, NullUserPointer(), NullUserPointer(), MOJO_WRITE_DATA_FLAG_NONE));
   EXPECT_EQ(1u, info.GetBeginWriteDataCallCount());
 
   EXPECT_EQ(0u, info.GetEndWriteDataCallCount());
-  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
-            core()->EndWriteData(h, 0));
+  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndWriteData(h, 0));
   EXPECT_EQ(1u, info.GetEndWriteDataCallCount());
 
   EXPECT_EQ(0u, info.GetReadDataCallCount());
-  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
-            core()->ReadData(h, NULL, NULL, MOJO_READ_DATA_FLAG_NONE));
+  EXPECT_EQ(
+      MOJO_RESULT_UNIMPLEMENTED,
+      core()->ReadData(
+          h, NullUserPointer(), NullUserPointer(), MOJO_READ_DATA_FLAG_NONE));
   EXPECT_EQ(1u, info.GetReadDataCallCount());
 
   EXPECT_EQ(0u, info.GetBeginReadDataCallCount());
-  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
-            core()->BeginReadData(h, NULL, NULL, MOJO_READ_DATA_FLAG_NONE));
+  EXPECT_EQ(
+      MOJO_RESULT_UNIMPLEMENTED,
+      core()->BeginReadData(
+          h, NullUserPointer(), NullUserPointer(), MOJO_READ_DATA_FLAG_NONE));
   EXPECT_EQ(1u, info.GetBeginReadDataCallCount());
 
   EXPECT_EQ(0u, info.GetEndReadDataCallCount());
-  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
-            core()->EndReadData(h, 0));
+  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0));
   EXPECT_EQ(1u, info.GetEndReadDataCallCount());
 
   EXPECT_EQ(0u, info.GetAddWaiterCallCount());
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE,
-                         MOJO_DEADLINE_INDEFINITE));
+            core()->Wait(h,
+                         ~MOJO_HANDLE_SIGNAL_NONE,
+                         MOJO_DEADLINE_INDEFINITE,
+                         NullUserPointer()));
   EXPECT_EQ(1u, info.GetAddWaiterCallCount());
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 0));
+            core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 0, NullUserPointer()));
   EXPECT_EQ(2u, info.GetAddWaiterCallCount());
+  MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000));
+            core()->Wait(h,
+                         ~MOJO_HANDLE_SIGNAL_NONE,
+                         MOJO_DEADLINE_INDEFINITE,
+                         MakeUserPointer(&hss)));
   EXPECT_EQ(3u, info.GetAddWaiterCallCount());
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
+  EXPECT_EQ(
+      MOJO_RESULT_FAILED_PRECONDITION,
+      core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, NullUserPointer()));
+  EXPECT_EQ(4u, info.GetAddWaiterCallCount());
+  hss = kFullMojoHandleSignalsState;
+  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+            core()->Wait(
+                h, ~MOJO_HANDLE_SIGNAL_NONE, 10 * 1000, MakeUserPointer(&hss)));
+  EXPECT_EQ(5u, info.GetAddWaiterCallCount());
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
+
   MojoHandleSignals handle_signals = ~MOJO_HANDLE_SIGNAL_NONE;
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->WaitMany(&h, &handle_signals, 1, MOJO_DEADLINE_INDEFINITE));
-  EXPECT_EQ(4u, info.GetAddWaiterCallCount());
+            core()->WaitMany(MakeUserPointer(&h),
+                             MakeUserPointer(&handle_signals),
+                             1,
+                             MOJO_DEADLINE_INDEFINITE,
+                             NullUserPointer(),
+                             NullUserPointer()));
+  EXPECT_EQ(6u, info.GetAddWaiterCallCount());
+  uint32_t result_index = static_cast<uint32_t>(-1);
+  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+            core()->WaitMany(MakeUserPointer(&h),
+                             MakeUserPointer(&handle_signals),
+                             1,
+                             MOJO_DEADLINE_INDEFINITE,
+                             MakeUserPointer(&result_index),
+                             NullUserPointer()));
+  EXPECT_EQ(7u, info.GetAddWaiterCallCount());
+  EXPECT_EQ(0u, result_index);
+  hss = kFullMojoHandleSignalsState;
+  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+            core()->WaitMany(MakeUserPointer(&h),
+                             MakeUserPointer(&handle_signals),
+                             1,
+                             MOJO_DEADLINE_INDEFINITE,
+                             NullUserPointer(),
+                             MakeUserPointer(&hss)));
+  EXPECT_EQ(8u, info.GetAddWaiterCallCount());
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
+  result_index = static_cast<uint32_t>(-1);
+  hss = kFullMojoHandleSignalsState;
+  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+            core()->WaitMany(MakeUserPointer(&h),
+                             MakeUserPointer(&handle_signals),
+                             1,
+                             MOJO_DEADLINE_INDEFINITE,
+                             MakeUserPointer(&result_index),
+                             MakeUserPointer(&hss)));
+  EXPECT_EQ(9u, info.GetAddWaiterCallCount());
+  EXPECT_EQ(0u, result_index);
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
 
   EXPECT_EQ(0u, info.GetDtorCallCount());
   EXPECT_EQ(0u, info.GetCloseCallCount());
@@ -139,11 +211,38 @@ TEST_F(CoreTest, InvalidArguments) {
   // |Wait()|:
   {
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->Wait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE,
-                           MOJO_DEADLINE_INDEFINITE));
+              core()->Wait(MOJO_HANDLE_INVALID,
+                           ~MOJO_HANDLE_SIGNAL_NONE,
+                           MOJO_DEADLINE_INDEFINITE,
+                           NullUserPointer()));
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->Wait(10, ~MOJO_HANDLE_SIGNAL_NONE,
-                           MOJO_DEADLINE_INDEFINITE));
+              core()->Wait(10,
+                           ~MOJO_HANDLE_SIGNAL_NONE,
+                           MOJO_DEADLINE_INDEFINITE,
+                           NullUserPointer()));
+
+    MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              core()->Wait(MOJO_HANDLE_INVALID,
+                           ~MOJO_HANDLE_SIGNAL_NONE,
+                           MOJO_DEADLINE_INDEFINITE,
+                           MakeUserPointer(&hss)));
+    // On invalid argument, it shouldn't modify the handle signals state.
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
+              hss.satisfied_signals);
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
+              hss.satisfiable_signals);
+    hss = kFullMojoHandleSignalsState;
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              core()->Wait(10,
+                           ~MOJO_HANDLE_SIGNAL_NONE,
+                           MOJO_DEADLINE_INDEFINITE,
+                           MakeUserPointer(&hss)));
+    // On invalid argument, it shouldn't modify the handle signals state.
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
+              hss.satisfied_signals);
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
+              hss.satisfiable_signals);
   }
 
   // |WaitMany()|:
@@ -152,102 +251,195 @@ TEST_F(CoreTest, InvalidArguments) {
     MojoHandleSignals signals[2] = {~MOJO_HANDLE_SIGNAL_NONE,
                                     ~MOJO_HANDLE_SIGNAL_NONE};
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WaitMany(handles, signals, 0, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(MakeUserPointer(handles),
+                               MakeUserPointer(signals),
+                               0,
+                               MOJO_DEADLINE_INDEFINITE,
+                               NullUserPointer(),
+                               NullUserPointer()));
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WaitMany(NULL, signals, 0, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(NullUserPointer(),
+                               MakeUserPointer(signals),
+                               0,
+                               MOJO_DEADLINE_INDEFINITE,
+                               NullUserPointer(),
+                               NullUserPointer()));
+    // If |num_handles| is invalid, it should leave |result_index| and
+    // |signals_states| alone.
+    // (We use -1 internally; make sure that doesn't leak.)
+    uint32_t result_index = 123;
+    MojoHandleSignalsState hss = kFullMojoHandleSignalsState;
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WaitMany(handles, NULL, 0, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(NullUserPointer(),
+                               MakeUserPointer(signals),
+                               0,
+                               MOJO_DEADLINE_INDEFINITE,
+                               MakeUserPointer(&result_index),
+                               MakeUserPointer(&hss)));
+    EXPECT_EQ(123u, result_index);
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
+              hss.satisfied_signals);
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
+              hss.satisfiable_signals);
 
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WaitMany(NULL, signals, 1, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(MakeUserPointer(handles),
+                               NullUserPointer(),
+                               0,
+                               MOJO_DEADLINE_INDEFINITE,
+                               NullUserPointer(),
+                               NullUserPointer()));
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WaitMany(handles, NULL, 1, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(MakeUserPointer(handles),
+                               MakeUserPointer(signals),
+                               1,
+                               MOJO_DEADLINE_INDEFINITE,
+                               NullUserPointer(),
+                               NullUserPointer()));
+    // But if a handle is bad, then it should set |result_index| but still leave
+    // |signals_states| alone.
+    result_index = static_cast<uint32_t>(-1);
+    hss = kFullMojoHandleSignalsState;
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WaitMany(handles, signals, 1, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(MakeUserPointer(handles),
+                               MakeUserPointer(signals),
+                               1,
+                               MOJO_DEADLINE_INDEFINITE,
+                               MakeUserPointer(&result_index),
+                               MakeUserPointer(&hss)));
+    EXPECT_EQ(0u, result_index);
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
+              hss.satisfied_signals);
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
+              hss.satisfiable_signals);
 
     MockHandleInfo info[2];
     handles[0] = CreateMockHandle(&info[0]);
 
+    result_index = static_cast<uint32_t>(-1);
+    hss = kFullMojoHandleSignalsState;
     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              core()->WaitMany(handles, signals, 1, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(MakeUserPointer(handles),
+                               MakeUserPointer(signals),
+                               1,
+                               MOJO_DEADLINE_INDEFINITE,
+                               MakeUserPointer(&result_index),
+                               MakeUserPointer(&hss)));
+    EXPECT_EQ(0u, result_index);
+    EXPECT_EQ(0u, hss.satisfied_signals);
+    EXPECT_EQ(0u, hss.satisfiable_signals);
+
+    // On invalid argument, it'll leave |signals_states| alone.
+    result_index = static_cast<uint32_t>(-1);
+    hss = kFullMojoHandleSignalsState;
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WaitMany(handles, signals, 2, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(MakeUserPointer(handles),
+                               MakeUserPointer(signals),
+                               2,
+                               MOJO_DEADLINE_INDEFINITE,
+                               MakeUserPointer(&result_index),
+                               MakeUserPointer(&hss)));
+    EXPECT_EQ(1u, result_index);
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfied_signals,
+              hss.satisfied_signals);
+    EXPECT_EQ(kFullMojoHandleSignalsState.satisfiable_signals,
+              hss.satisfiable_signals);
     handles[1] = handles[0] + 1;  // Invalid handle.
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WaitMany(handles, signals, 2, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(MakeUserPointer(handles),
+                               MakeUserPointer(signals),
+                               2,
+                               MOJO_DEADLINE_INDEFINITE,
+                               NullUserPointer(),
+                               NullUserPointer()));
     handles[1] = CreateMockHandle(&info[1]);
     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-              core()->WaitMany(handles, signals, 2, MOJO_DEADLINE_INDEFINITE));
+              core()->WaitMany(MakeUserPointer(handles),
+                               MakeUserPointer(signals),
+                               2,
+                               MOJO_DEADLINE_INDEFINITE,
+                               NullUserPointer(),
+                               NullUserPointer()));
+
+    // TODO(vtl): Test one where we get "failed precondition" only for the
+    // second handle (and the first one is valid to wait on).
 
     EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[0]));
     EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[1]));
   }
 
-  // |CreateMessagePipe()|:
-  {
-    MojoHandle h;
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->CreateMessagePipe(NULL, NULL, NULL));
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->CreateMessagePipe(NULL, &h, NULL));
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->CreateMessagePipe(NULL, NULL, &h));
-  }
+  // |CreateMessagePipe()|: Nothing to check (apart from things that cause
+  // death).
 
   // |WriteMessage()|:
   // Only check arguments checked by |Core|, namely |handle|, |handles|, and
   // |num_handles|.
   {
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WriteMessage(MOJO_HANDLE_INVALID, NULL, 0, NULL, 0,
+              core()->WriteMessage(MOJO_HANDLE_INVALID,
+                                   NullUserPointer(),
+                                   0,
+                                   NullUserPointer(),
+                                   0,
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
 
     MockHandleInfo info;
     MojoHandle h = CreateMockHandle(&info);
     MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID};
 
-    // Null |handles| with nonzero |num_handles|.
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WriteMessage(h, NULL, 0, NULL, 1,
-                                   MOJO_WRITE_MESSAGE_FLAG_NONE));
-    // Checked by |Core|, shouldn't go through to the dispatcher.
-    EXPECT_EQ(0u, info.GetWriteMessageCallCount());
-
     // Huge handle count (implausibly big on some systems -- more than can be
     // stored in a 32-bit address space).
     // Note: This may return either |MOJO_RESULT_INVALID_ARGUMENT| or
     // |MOJO_RESULT_RESOURCE_EXHAUSTED|, depending on whether it's plausible or
     // not.
     EXPECT_NE(MOJO_RESULT_OK,
-              core()->WriteMessage(h, NULL, 0, handles,
+              core()->WriteMessage(h,
+                                   NullUserPointer(),
+                                   0,
+                                   MakeUserPointer(handles),
                                    std::numeric_limits<uint32_t>::max(),
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(0u, info.GetWriteMessageCallCount());
 
     // Huge handle count (plausibly big).
     EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
-              core()->WriteMessage(h, NULL, 0, handles,
-                                   std::numeric_limits<uint32_t>::max() /
-                                       sizeof(handles[0]),
-                                   MOJO_WRITE_MESSAGE_FLAG_NONE));
+              core()->WriteMessage(
+                  h,
+                  NullUserPointer(),
+                  0,
+                  MakeUserPointer(handles),
+                  std::numeric_limits<uint32_t>::max() / sizeof(handles[0]),
+                  MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(0u, info.GetWriteMessageCallCount());
 
     // Invalid handle in |handles|.
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WriteMessage(h, NULL, 0, handles, 1,
+              core()->WriteMessage(h,
+                                   NullUserPointer(),
+                                   0,
+                                   MakeUserPointer(handles),
+                                   1,
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(0u, info.GetWriteMessageCallCount());
 
     // Two invalid handles in |handles|.
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WriteMessage(h, NULL, 0, handles, 2,
+              core()->WriteMessage(h,
+                                   NullUserPointer(),
+                                   0,
+                                   MakeUserPointer(handles),
+                                   2,
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(0u, info.GetWriteMessageCallCount());
 
     // Can't send a handle over itself.
     handles[0] = h;
     EXPECT_EQ(MOJO_RESULT_BUSY,
-              core()->WriteMessage(h, NULL, 0, handles, 1,
+              core()->WriteMessage(h,
+                                   NullUserPointer(),
+                                   0,
+                                   MakeUserPointer(handles),
+                                   1,
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(0u, info.GetWriteMessageCallCount());
 
@@ -257,27 +449,43 @@ TEST_F(CoreTest, InvalidArguments) {
     // This is "okay", but |MockDispatcher| doesn't implement it.
     handles[0] = h2;
     EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
-              core()->WriteMessage(h, NULL, 0, handles, 1,
+              core()->WriteMessage(h,
+                                   NullUserPointer(),
+                                   0,
+                                   MakeUserPointer(handles),
+                                   1,
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(1u, info.GetWriteMessageCallCount());
 
     // One of the |handles| is still invalid.
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->WriteMessage(h, NULL, 0, handles, 2,
+              core()->WriteMessage(h,
+                                   NullUserPointer(),
+                                   0,
+                                   MakeUserPointer(handles),
+                                   2,
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(1u, info.GetWriteMessageCallCount());
 
     // One of the |handles| is the same as |handle|.
     handles[1] = h;
     EXPECT_EQ(MOJO_RESULT_BUSY,
-              core()->WriteMessage(h, NULL, 0, handles, 2,
+              core()->WriteMessage(h,
+                                   NullUserPointer(),
+                                   0,
+                                   MakeUserPointer(handles),
+                                   2,
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(1u, info.GetWriteMessageCallCount());
 
     // Can't send a handle twice in the same message.
     handles[1] = h2;
     EXPECT_EQ(MOJO_RESULT_BUSY,
-              core()->WriteMessage(h, NULL, 0, handles, 2,
+              core()->WriteMessage(h,
+                                   NullUserPointer(),
+                                   0,
+                                   MakeUserPointer(handles),
+                                   2,
                                    MOJO_WRITE_MESSAGE_FLAG_NONE));
     EXPECT_EQ(1u, info.GetWriteMessageCallCount());
 
@@ -293,23 +501,24 @@ TEST_F(CoreTest, InvalidArguments) {
   // |num_handles|.
   {
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->ReadMessage(MOJO_HANDLE_INVALID, NULL, NULL, NULL, NULL,
+              core()->ReadMessage(MOJO_HANDLE_INVALID,
+                                  NullUserPointer(),
+                                  NullUserPointer(),
+                                  NullUserPointer(),
+                                  NullUserPointer(),
                                   MOJO_READ_MESSAGE_FLAG_NONE));
 
     MockHandleInfo info;
     MojoHandle h = CreateMockHandle(&info);
 
-    uint32_t handle_count = 1;
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              core()->ReadMessage(h, NULL, NULL, NULL, &handle_count,
-                                  MOJO_READ_MESSAGE_FLAG_NONE));
-    // Checked by |Core|, shouldn't go through to the dispatcher.
-    EXPECT_EQ(0u, info.GetReadMessageCallCount());
-
     // Okay.
-    handle_count = 0;
+    uint32_t handle_count = 0;
     EXPECT_EQ(MOJO_RESULT_OK,
-              core()->ReadMessage(h, NULL, NULL, NULL, &handle_count,
+              core()->ReadMessage(h,
+                                  NullUserPointer(),
+                                  NullUserPointer(),
+                                  NullUserPointer(),
+                                  MakeUserPointer(&handle_count),
                                   MOJO_READ_MESSAGE_FLAG_NONE));
     // Checked by |Core|, shouldn't go through to the dispatcher.
     EXPECT_EQ(1u, info.GetReadMessageCallCount());
@@ -318,14 +527,108 @@ TEST_F(CoreTest, InvalidArguments) {
   }
 }
 
+// These test invalid arguments that should cause death if we're being paranoid
+// about checking arguments (which we would want to do if, e.g., we were in a
+// true "kernel" situation, but we might not want to do otherwise for
+// performance reasons). Probably blatant errors like passing in null pointers
+// (for required pointer arguments) will still cause death, but perhaps not
+// predictably.
+TEST_F(CoreTest, InvalidArgumentsDeath) {
+  const char kMemoryCheckFailedRegex[] = "Check failed";
+
+  // |WaitMany()|:
+  {
+    MojoHandle handle = MOJO_HANDLE_INVALID;
+    MojoHandleSignals signals = ~MOJO_HANDLE_SIGNAL_NONE;
+    EXPECT_DEATH_IF_SUPPORTED(core()->WaitMany(NullUserPointer(),
+                                               MakeUserPointer(&signals),
+                                               1,
+                                               MOJO_DEADLINE_INDEFINITE,
+                                               NullUserPointer(),
+                                               NullUserPointer()),
+                              kMemoryCheckFailedRegex);
+    EXPECT_DEATH_IF_SUPPORTED(core()->WaitMany(MakeUserPointer(&handle),
+                                               NullUserPointer(),
+                                               1,
+                                               MOJO_DEADLINE_INDEFINITE,
+                                               NullUserPointer(),
+                                               NullUserPointer()),
+                              kMemoryCheckFailedRegex);
+    // TODO(vtl): |result_index| and |signals_states| are optional. Test them
+    // with non-null invalid pointers?
+  }
+
+  // |CreateMessagePipe()|:
+  {
+    MojoHandle h;
+    EXPECT_DEATH_IF_SUPPORTED(
+        core()->CreateMessagePipe(
+            NullUserPointer(), NullUserPointer(), NullUserPointer()),
+        kMemoryCheckFailedRegex);
+    EXPECT_DEATH_IF_SUPPORTED(
+        core()->CreateMessagePipe(
+            NullUserPointer(), MakeUserPointer(&h), NullUserPointer()),
+        kMemoryCheckFailedRegex);
+    EXPECT_DEATH_IF_SUPPORTED(
+        core()->CreateMessagePipe(
+            NullUserPointer(), NullUserPointer(), MakeUserPointer(&h)),
+        kMemoryCheckFailedRegex);
+  }
+
+  // |WriteMessage()|:
+  // Only check arguments checked by |Core|, namely |handle|, |handles|, and
+  // |num_handles|.
+  {
+    MockHandleInfo info;
+    MojoHandle h = CreateMockHandle(&info);
+
+    // Null |handles| with nonzero |num_handles|.
+    EXPECT_DEATH_IF_SUPPORTED(
+        core()->WriteMessage(h,
+                             NullUserPointer(),
+                             0,
+                             NullUserPointer(),
+                             1,
+                             MOJO_WRITE_MESSAGE_FLAG_NONE),
+        kMemoryCheckFailedRegex);
+
+    EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
+  }
+
+  // |ReadMessage()|:
+  // Only check arguments checked by |Core|, namely |handle|, |handles|, and
+  // |num_handles|.
+  {
+    MockHandleInfo info;
+    MojoHandle h = CreateMockHandle(&info);
+
+    uint32_t handle_count = 1;
+    EXPECT_DEATH_IF_SUPPORTED(
+        core()->ReadMessage(h,
+                            NullUserPointer(),
+                            NullUserPointer(),
+                            NullUserPointer(),
+                            MakeUserPointer(&handle_count),
+                            MOJO_READ_MESSAGE_FLAG_NONE),
+        kMemoryCheckFailedRegex);
+
+    EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
+  }
+}
+
 // TODO(vtl): test |Wait()| and |WaitMany()| properly
 //  - including |WaitMany()| with the same handle more than once (with
 //    same/different signals)
 
 TEST_F(CoreTest, MessagePipe) {
   MojoHandle h[2];
+  MojoHandleSignalsState hss[2];
+  uint32_t result_index;
 
-  EXPECT_EQ(MOJO_RESULT_OK, core()->CreateMessagePipe(NULL, &h[0], &h[1]));
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      core()->CreateMessagePipe(
+          NullUserPointer(), MakeUserPointer(&h[0]), MakeUserPointer(&h[1])));
   // Should get two distinct, valid handles.
   EXPECT_NE(h[0], MOJO_HANDLE_INVALID);
   EXPECT_NE(h[1], MOJO_HANDLE_INVALID);
@@ -334,91 +637,205 @@ TEST_F(CoreTest, MessagePipe) {
   // Neither should be readable.
   MojoHandleSignals signals[2] = {MOJO_HANDLE_SIGNAL_READABLE,
                                   MOJO_HANDLE_SIGNAL_READABLE};
+  result_index = static_cast<uint32_t>(-1);
+  hss[0] = kEmptyMojoHandleSignalsState;
+  hss[1] = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            core()->WaitMany(h, signals, 2, 0));
+            core()->WaitMany(MakeUserPointer(h),
+                             MakeUserPointer(signals),
+                             2,
+                             0,
+                             MakeUserPointer(&result_index),
+                             MakeUserPointer(hss)));
+  EXPECT_EQ(static_cast<uint32_t>(-1), result_index);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[0].satisfiable_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[1].satisfiable_signals);
 
   // Try to read anyway.
   char buffer[1] = {'a'};
   uint32_t buffer_size = 1;
   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
-            core()->ReadMessage(h[0], buffer, &buffer_size, NULL, NULL,
+            core()->ReadMessage(h[0],
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&buffer_size),
+                                NullUserPointer(),
+                                NullUserPointer(),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   // Check that it left its inputs alone.
   EXPECT_EQ('a', buffer[0]);
   EXPECT_EQ(1u, buffer_size);
 
   // Both should be writable.
+  hss[0] = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h[0], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000));
+            core()->Wait(h[0],
+                         MOJO_HANDLE_SIGNAL_WRITABLE,
+                         1000000000,
+                         MakeUserPointer(&hss[0])));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[0].satisfiable_signals);
+  hss[0] = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000));
+            core()->Wait(h[1],
+                         MOJO_HANDLE_SIGNAL_WRITABLE,
+                         1000000000,
+                         MakeUserPointer(&hss[0])));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[0].satisfiable_signals);
 
   // Also check that |h[1]| is writable using |WaitMany()|.
   signals[0] = MOJO_HANDLE_SIGNAL_READABLE;
   signals[1] = MOJO_HANDLE_SIGNAL_WRITABLE;
-  EXPECT_EQ(1, core()->WaitMany(h, signals, 2, MOJO_DEADLINE_INDEFINITE));
+  result_index = static_cast<uint32_t>(-1);
+  hss[0] = kEmptyMojoHandleSignalsState;
+  hss[1] = kEmptyMojoHandleSignalsState;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            core()->WaitMany(MakeUserPointer(h),
+                             MakeUserPointer(signals),
+                             2,
+                             MOJO_DEADLINE_INDEFINITE,
+                             MakeUserPointer(&result_index),
+                             MakeUserPointer(hss)));
+  EXPECT_EQ(1u, result_index);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[0].satisfiable_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[1].satisfiable_signals);
 
   // Write to |h[1]|.
   buffer[0] = 'b';
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->WriteMessage(h[1], buffer, 1, NULL, 0,
+            core()->WriteMessage(h[1],
+                                 UserPointer<const void>(buffer),
+                                 1,
+                                 NullUserPointer(),
+                                 0,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
 
   // Check that |h[0]| is now readable.
   signals[0] = MOJO_HANDLE_SIGNAL_READABLE;
   signals[1] = MOJO_HANDLE_SIGNAL_READABLE;
-  EXPECT_EQ(0, core()->WaitMany(h, signals, 2, MOJO_DEADLINE_INDEFINITE));
+  result_index = static_cast<uint32_t>(-1);
+  hss[0] = kEmptyMojoHandleSignalsState;
+  hss[1] = kEmptyMojoHandleSignalsState;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            core()->WaitMany(MakeUserPointer(h),
+                             MakeUserPointer(signals),
+                             2,
+                             MOJO_DEADLINE_INDEFINITE,
+                             MakeUserPointer(&result_index),
+                             MakeUserPointer(hss)));
+  EXPECT_EQ(0u, result_index);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[0].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[0].satisfiable_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[1].satisfiable_signals);
 
   // Read from |h[0]|.
   // First, get only the size.
   buffer_size = 0;
   EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
-            core()->ReadMessage(h[0], NULL, &buffer_size, NULL, NULL,
+            core()->ReadMessage(h[0],
+                                NullUserPointer(),
+                                MakeUserPointer(&buffer_size),
+                                NullUserPointer(),
+                                NullUserPointer(),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(1u, buffer_size);
   // Then actually read it.
   buffer[0] = 'c';
   buffer_size = 1;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->ReadMessage(h[0], buffer, &buffer_size, NULL, NULL,
+            core()->ReadMessage(h[0],
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&buffer_size),
+                                NullUserPointer(),
+                                NullUserPointer(),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ('b', buffer[0]);
   EXPECT_EQ(1u, buffer_size);
 
   // |h[0]| should no longer be readable.
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            core()->Wait(h[0], MOJO_HANDLE_SIGNAL_READABLE, 0));
+  hss[0] = kEmptyMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_DEADLINE_EXCEEDED,
+      core()->Wait(
+          h[0], MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss[0])));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss[0].satisfiable_signals);
 
   // Write to |h[0]|.
   buffer[0] = 'd';
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->WriteMessage(h[0], buffer, 1, NULL, 0,
+            core()->WriteMessage(h[0],
+                                 UserPointer<const void>(buffer),
+                                 1,
+                                 NullUserPointer(),
+                                 0,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
 
   // Close |h[0]|.
   EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[0]));
 
   // Check that |h[1]| is no longer writable (and will never be).
+  hss[0] = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000));
+            core()->Wait(h[1],
+                         MOJO_HANDLE_SIGNAL_WRITABLE,
+                         1000000000,
+                         MakeUserPointer(&hss[0])));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfiable_signals);
 
   // Check that |h[1]| is still readable (for the moment).
+  hss[0] = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000));
+            core()->Wait(h[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss[0])));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfiable_signals);
 
   // Discard a message from |h[1]|.
   EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
-            core()->ReadMessage(h[1], NULL, NULL, NULL, NULL,
+            core()->ReadMessage(h[1],
+                                NullUserPointer(),
+                                NullUserPointer(),
+                                NullUserPointer(),
+                                NullUserPointer(),
                                 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD));
 
   // |h[1]| is no longer readable (and will never be).
+  hss[0] = kFullMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000));
+            core()->Wait(h[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss[0])));
+  EXPECT_EQ(0u, hss[0].satisfied_signals);
+  EXPECT_EQ(0u, hss[0].satisfiable_signals);
 
   // Try writing to |h[1]|.
   buffer[0] = 'e';
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->WriteMessage(h[1], buffer, 1, NULL, 0,
+            core()->WriteMessage(h[1],
+                                 UserPointer<const void>(buffer),
+                                 1,
+                                 NullUserPointer(),
+                                 0,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
 
   EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h[1]));
@@ -435,27 +852,41 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
   uint32_t num_bytes;
   MojoHandle handles[10];
   uint32_t num_handles;
+  MojoHandleSignalsState hss;
   MojoHandle h_received;
 
   MojoHandle h_passing[2];
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->CreateMessagePipe(NULL, &h_passing[0], &h_passing[1]));
+            core()->CreateMessagePipe(NullUserPointer(),
+                                      MakeUserPointer(&h_passing[0]),
+                                      MakeUserPointer(&h_passing[1])));
 
   // Make sure that |h_passing[]| work properly.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passing[0],
-                                 kHello, kHelloSize,
-                                 NULL, 0,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 NullUserPointer(),
+                                 0,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE,
-                         1000000000));
+            core()->Wait(h_passing[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
   num_bytes = kBufferSize;
   num_handles = arraysize(handles);
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->ReadMessage(h_passing[1],
-                                buffer, &num_bytes,
-                                handles, &num_handles,
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&num_bytes),
+                                MakeUserPointer(handles),
+                                MakeUserPointer(&num_handles),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kHelloSize, num_bytes);
   EXPECT_STREQ(kHello, buffer);
@@ -465,33 +896,51 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
   // itself.
   EXPECT_EQ(MOJO_RESULT_BUSY,
             core()->WriteMessage(h_passing[0],
-                                 kHello, kHelloSize,
-                                 &h_passing[0], 1,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 MakeUserPointer(&h_passing[0]),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
             core()->WriteMessage(h_passing[0],
-                                 kHello, kHelloSize,
-                                 &h_passing[1], 1,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 MakeUserPointer(&h_passing[1]),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
 
   MojoHandle h_passed[2];
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->CreateMessagePipe(NULL, &h_passed[0], &h_passed[1]));
+            core()->CreateMessagePipe(NullUserPointer(),
+                                      MakeUserPointer(&h_passed[0]),
+                                      MakeUserPointer(&h_passed[1])));
 
   // Make sure that |h_passed[]| work properly.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passed[0],
-                                 kHello, kHelloSize,
-                                 NULL, 0,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 NullUserPointer(),
+                                 0,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h_passed[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000));
+            core()->Wait(h_passed[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
   num_bytes = kBufferSize;
   num_handles = arraysize(handles);
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->ReadMessage(h_passed[1],
-                                buffer, &num_bytes,
-                                handles, &num_handles,
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&num_bytes),
+                                MakeUserPointer(handles),
+                                MakeUserPointer(&num_handles),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kHelloSize, num_bytes);
   EXPECT_STREQ(kHello, buffer);
@@ -500,18 +949,29 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
   // Send |h_passed[1]| from |h_passing[0]| to |h_passing[1]|.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passing[0],
-                                 kWorld, kWorldSize,
-                                 &h_passed[1], 1,
+                                 UserPointer<const void>(kWorld),
+                                 kWorldSize,
+                                 MakeUserPointer(&h_passed[1]),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE,
-                         1000000000));
+            core()->Wait(h_passing[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
   num_bytes = kBufferSize;
   num_handles = arraysize(handles);
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->ReadMessage(h_passing[1],
-                                buffer, &num_bytes,
-                                handles, &num_handles,
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&num_bytes),
+                                MakeUserPointer(handles),
+                                MakeUserPointer(&num_handles),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kWorldSize, num_bytes);
   EXPECT_STREQ(kWorld, buffer);
@@ -532,17 +992,29 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
   // Write to |h_passed[0]|. Should receive on |h_received|.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passed[0],
-                                 kHello, kHelloSize,
-                                 NULL, 0,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 NullUserPointer(),
+                                 0,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000));
+            core()->Wait(h_received,
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
   num_bytes = kBufferSize;
   num_handles = arraysize(handles);
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->ReadMessage(h_received,
-                                buffer, &num_bytes,
-                                handles, &num_handles,
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&num_bytes),
+                                MakeUserPointer(handles),
+                                MakeUserPointer(&num_handles),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kHelloSize, num_bytes);
   EXPECT_STREQ(kHello, buffer);
@@ -556,43 +1028,70 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing1) {
 
 TEST_F(CoreTest, DataPipe) {
   MojoHandle ph, ch;  // p is for producer and c is for consumer.
+  MojoHandleSignalsState hss;
 
-  EXPECT_EQ(MOJO_RESULT_OK, core()->CreateDataPipe(NULL, &ph, &ch));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            core()->CreateDataPipe(
+                NullUserPointer(), MakeUserPointer(&ph), MakeUserPointer(&ch)));
   // Should get two distinct, valid handles.
   EXPECT_NE(ph, MOJO_HANDLE_INVALID);
   EXPECT_NE(ch, MOJO_HANDLE_INVALID);
   EXPECT_NE(ph, ch);
 
   // Producer should be never-readable, but already writable.
-  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->Wait(ph, MOJO_HANDLE_SIGNAL_READABLE, 0));
-  EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(ph, MOJO_HANDLE_SIGNAL_WRITABLE, 0));
+  hss = kEmptyMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_FAILED_PRECONDITION,
+      core()->Wait(ph, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+  hss = kEmptyMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      core()->Wait(ph, MOJO_HANDLE_SIGNAL_WRITABLE, 0, MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
 
   // Consumer should be never-writable, and not yet readable.
-  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->Wait(ch, MOJO_HANDLE_SIGNAL_WRITABLE, 0));
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0));
+  hss = kFullMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_FAILED_PRECONDITION,
+      core()->Wait(ch, MOJO_HANDLE_SIGNAL_WRITABLE, 0, MakeUserPointer(&hss)));
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+  hss = kFullMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_DEADLINE_EXCEEDED,
+      core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // Write.
   char elements[2] = {'A', 'B'};
   uint32_t num_bytes = 2u;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->WriteData(ph, elements, &num_bytes,
+            core()->WriteData(ph,
+                              UserPointer<const void>(elements),
+                              MakeUserPointer(&num_bytes),
                               MOJO_WRITE_DATA_FLAG_NONE));
   EXPECT_EQ(2u, num_bytes);
 
   // Consumer should now be readable.
-  EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0));
+  hss = kEmptyMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // Read one character.
   elements[0] = -1;
   elements[1] = -1;
   num_bytes = 1u;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->ReadData(ch, elements, &num_bytes,
+            core()->ReadData(ch,
+                             UserPointer<void>(elements),
+                             MakeUserPointer(&num_bytes),
                              MOJO_READ_DATA_FLAG_NONE));
   EXPECT_EQ('A', elements[0]);
   EXPECT_EQ(-1, elements[1]);
@@ -601,7 +1100,9 @@ TEST_F(CoreTest, DataPipe) {
   void* write_ptr = NULL;
   num_bytes = 0u;
   ASSERT_EQ(MOJO_RESULT_OK,
-            core()->BeginWriteData(ph, &write_ptr, &num_bytes,
+            core()->BeginWriteData(ph,
+                                   MakeUserPointer(&write_ptr),
+                                   MakeUserPointer(&num_bytes),
                                    MOJO_WRITE_DATA_FLAG_NONE));
   // We count on the default options providing a decent buffer size.
   ASSERT_GE(num_bytes, 3u);
@@ -610,7 +1111,9 @@ TEST_F(CoreTest, DataPipe) {
   elements[0] = 'X';
   num_bytes = 1u;
   EXPECT_EQ(MOJO_RESULT_BUSY,
-            core()->WriteData(ph, elements, &num_bytes,
+            core()->WriteData(ph,
+                              UserPointer<const void>(elements),
+                              MakeUserPointer(&num_bytes),
                               MOJO_WRITE_DATA_FLAG_NONE));
 
   // Actually write the data, and complete it now.
@@ -622,28 +1125,37 @@ TEST_F(CoreTest, DataPipe) {
   // Query how much data we have.
   num_bytes = 0;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->ReadData(ch, NULL, &num_bytes, MOJO_READ_DATA_FLAG_QUERY));
+            core()->ReadData(ch,
+                             NullUserPointer(),
+                             MakeUserPointer(&num_bytes),
+                             MOJO_READ_DATA_FLAG_QUERY));
   EXPECT_EQ(4u, num_bytes);
 
   // Try to discard ten characters, in all-or-none mode. Should fail.
   num_bytes = 10;
   EXPECT_EQ(MOJO_RESULT_OUT_OF_RANGE,
-            core()->ReadData(ch, NULL, &num_bytes,
-                             MOJO_READ_DATA_FLAG_DISCARD |
-                                 MOJO_READ_DATA_FLAG_ALL_OR_NONE));
+            core()->ReadData(
+                ch,
+                NullUserPointer(),
+                MakeUserPointer(&num_bytes),
+                MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE));
 
   // Discard two characters.
   num_bytes = 2;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->ReadData(ch, NULL, &num_bytes,
-                             MOJO_READ_DATA_FLAG_DISCARD |
-                                 MOJO_READ_DATA_FLAG_ALL_OR_NONE));
+            core()->ReadData(
+                ch,
+                NullUserPointer(),
+                MakeUserPointer(&num_bytes),
+                MOJO_READ_DATA_FLAG_DISCARD | MOJO_READ_DATA_FLAG_ALL_OR_NONE));
 
   // Read the remaining two characters, in two-phase mode (all-or-none).
   const void* read_ptr = NULL;
   num_bytes = 2;
   ASSERT_EQ(MOJO_RESULT_OK,
-            core()->BeginReadData(ch, &read_ptr, &num_bytes,
+            core()->BeginReadData(ch,
+                                  MakeUserPointer(&read_ptr),
+                                  MakeUserPointer(&num_bytes),
                                   MOJO_READ_DATA_FLAG_ALL_OR_NONE));
   // Note: Count on still being able to do the contiguous read here.
   ASSERT_EQ(2u, num_bytes);
@@ -651,7 +1163,9 @@ TEST_F(CoreTest, DataPipe) {
   // Discarding right now should fail.
   num_bytes = 1;
   EXPECT_EQ(MOJO_RESULT_BUSY,
-            core()->ReadData(ch, NULL, &num_bytes,
+            core()->ReadData(ch,
+                             NullUserPointer(),
+                             MakeUserPointer(&num_bytes),
                              MOJO_READ_DATA_FLAG_DISCARD));
 
   // Actually check our data and end the two-phase read.
@@ -660,8 +1174,12 @@ TEST_F(CoreTest, DataPipe) {
   EXPECT_EQ(MOJO_RESULT_OK, core()->EndReadData(ch, 2u));
 
   // Consumer should now be no longer readable.
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0));
+  hss = kFullMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_DEADLINE_EXCEEDED,
+      core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // TODO(vtl): More.
 
@@ -669,8 +1187,12 @@ TEST_F(CoreTest, DataPipe) {
   EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ph));
 
   // The consumer should now be never-readable.
-  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0));
+  hss = kFullMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_FAILED_PRECONDITION,
+      core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
+  EXPECT_EQ(0u, hss.satisfied_signals);
+  EXPECT_EQ(0u, hss.satisfiable_signals);
 
   EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch));
 }
@@ -686,30 +1208,45 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
   uint32_t num_bytes;
   MojoHandle handles[10];
   uint32_t num_handles;
+  MojoHandleSignalsState hss;
 
   MojoHandle h_passing[2];
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->CreateMessagePipe(NULL, &h_passing[0], &h_passing[1]));
+            core()->CreateMessagePipe(NullUserPointer(),
+                                      MakeUserPointer(&h_passing[0]),
+                                      MakeUserPointer(&h_passing[1])));
 
   MojoHandle ph, ch;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->CreateDataPipe(NULL, &ph, &ch));
+            core()->CreateDataPipe(
+                NullUserPointer(), MakeUserPointer(&ph), MakeUserPointer(&ch)));
 
   // Send |ch| from |h_passing[0]| to |h_passing[1]|.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passing[0],
-                                 kHello, kHelloSize,
-                                 &ch, 1,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 MakeUserPointer(&ch),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE,
-                         1000000000));
+            core()->Wait(h_passing[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
   num_bytes = kBufferSize;
   num_handles = arraysize(handles);
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->ReadMessage(h_passing[1],
-                                buffer, &num_bytes,
-                                handles, &num_handles,
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&num_bytes),
+                                MakeUserPointer(handles),
+                                MakeUserPointer(&num_handles),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kHelloSize, num_bytes);
   EXPECT_STREQ(kHello, buffer);
@@ -730,13 +1267,23 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
   // Write to |ph|. Should receive on |ch_received|.
   num_bytes = kWorldSize;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->WriteData(ph, kWorld, &num_bytes,
+            core()->WriteData(ph,
+                              UserPointer<const void>(kWorld),
+                              MakeUserPointer(&num_bytes),
                               MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000));
+            core()->Wait(ch_received,
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
   num_bytes = kBufferSize;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->ReadData(ch_received, buffer, &num_bytes,
+            core()->ReadData(ch_received,
+                             UserPointer<void>(buffer),
+                             MakeUserPointer(&num_bytes),
                              MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kWorldSize, num_bytes);
   EXPECT_STREQ(kWorld, buffer);
@@ -744,18 +1291,29 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
   // Now pass |ph| in the same direction.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passing[0],
-                                 kWorld, kWorldSize,
-                                 &ph, 1,
+                                 UserPointer<const void>(kWorld),
+                                 kWorldSize,
+                                 MakeUserPointer(&ph),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE,
-                         1000000000));
+            core()->Wait(h_passing[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
   num_bytes = kBufferSize;
   num_handles = arraysize(handles);
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->ReadMessage(h_passing[1],
-                                buffer, &num_bytes,
-                                handles, &num_handles,
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&num_bytes),
+                                MakeUserPointer(handles),
+                                MakeUserPointer(&num_handles),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kWorldSize, num_bytes);
   EXPECT_STREQ(kWorld, buffer);
@@ -776,13 +1334,23 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
   // Write to |ph_received|. Should receive on |ch_received|.
   num_bytes = kHelloSize;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->WriteData(ph_received, kHello, &num_bytes,
+            core()->WriteData(ph_received,
+                              UserPointer<const void>(kHello),
+                              MakeUserPointer(&num_bytes),
                               MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000));
+            core()->Wait(ch_received,
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
   num_bytes = kBufferSize;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->ReadData(ch_received, buffer, &num_bytes,
+            core()->ReadData(ch_received,
+                             UserPointer<void>(buffer),
+                             MakeUserPointer(&num_bytes),
                              MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kHelloSize, num_bytes);
   EXPECT_STREQ(kHello, buffer);
@@ -796,31 +1364,41 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
   void* write_ptr = NULL;
   num_bytes = 0;
   ASSERT_EQ(MOJO_RESULT_OK,
-            core()->BeginWriteData(ph, &write_ptr, &num_bytes,
+            core()->BeginWriteData(ph,
+                                   MakeUserPointer(&write_ptr),
+                                   MakeUserPointer(&num_bytes),
                                    MOJO_WRITE_DATA_FLAG_NONE));
   ASSERT_GE(num_bytes, 1u);
   EXPECT_EQ(MOJO_RESULT_BUSY,
             core()->WriteMessage(h_passing[0],
-                                 kHello, kHelloSize,
-                                 &ph, 1,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 MakeUserPointer(&ph),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
 
   // But |ch| can, even if |ph| is in a two-phase write.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passing[0],
-                                 kHello, kHelloSize,
-                                 &ch, 1,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 MakeUserPointer(&ch),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
   ch = MOJO_HANDLE_INVALID;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE,
-                         1000000000));
+            core()->Wait(h_passing[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         NullUserPointer()));
   num_bytes = kBufferSize;
   num_handles = arraysize(handles);
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->ReadMessage(h_passing[1],
-                                buffer, &num_bytes,
-                                handles, &num_handles,
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&num_bytes),
+                                MakeUserPointer(handles),
+                                MakeUserPointer(&num_handles),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kHelloSize, num_bytes);
   EXPECT_STREQ(kHello, buffer);
@@ -833,37 +1411,57 @@ TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing2) {
   EXPECT_EQ(MOJO_RESULT_OK, core()->EndWriteData(ph, 1));
 
   // Wait for |ch| to be readable.
-  EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 1000000000));
+  hss = kEmptyMojoHandleSignalsState;
+  EXPECT_EQ(
+      MOJO_RESULT_OK,
+      core()->Wait(
+          ch, MOJO_HANDLE_SIGNAL_READABLE, 1000000000, MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
 
   // Make sure that |ch| can't be sent if it's in a two-phase read.
   const void* read_ptr = NULL;
   num_bytes = 1;
   ASSERT_EQ(MOJO_RESULT_OK,
-            core()->BeginReadData(ch, &read_ptr, &num_bytes,
+            core()->BeginReadData(ch,
+                                  MakeUserPointer(&read_ptr),
+                                  MakeUserPointer(&num_bytes),
                                   MOJO_READ_DATA_FLAG_ALL_OR_NONE));
   EXPECT_EQ(MOJO_RESULT_BUSY,
             core()->WriteMessage(h_passing[0],
-                                 kHello, kHelloSize,
-                                 &ch, 1,
+                                 UserPointer<const void>(kHello),
+                                 kHelloSize,
+                                 MakeUserPointer(&ch),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
 
   // But |ph| can, even if |ch| is in a two-phase read.
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->WriteMessage(h_passing[0],
-                                 kWorld, kWorldSize,
-                                 &ph, 1,
+                                 UserPointer<const void>(kWorld),
+                                 kWorldSize,
+                                 MakeUserPointer(&ph),
+                                 1,
                                  MOJO_WRITE_MESSAGE_FLAG_NONE));
   ph = MOJO_HANDLE_INVALID;
+  hss = kEmptyMojoHandleSignalsState;
   EXPECT_EQ(MOJO_RESULT_OK,
-            core()->Wait(h_passing[1], MOJO_HANDLE_SIGNAL_READABLE,
-                         1000000000));
+            core()->Wait(h_passing[1],
+                         MOJO_HANDLE_SIGNAL_READABLE,
+                         1000000000,
+                         MakeUserPointer(&hss)));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+            hss.satisfiable_signals);
   num_bytes = kBufferSize;
   num_handles = arraysize(handles);
   EXPECT_EQ(MOJO_RESULT_OK,
             core()->ReadMessage(h_passing[1],
-                                buffer, &num_bytes,
-                                handles, &num_handles,
+                                UserPointer<void>(buffer),
+                                MakeUserPointer(&num_bytes),
+                                MakeUserPointer(handles),
+                                MakeUserPointer(&num_handles),
                                 MOJO_READ_MESSAGE_FLAG_NONE));
   EXPECT_EQ(kWorldSize, num_bytes);
   EXPECT_STREQ(kWorld, buffer);