Split mojo/public/cpp/system/tests/core_unittest.cc, part 1.

R=azani@chromium.org

Review URL: https://codereview.chromium.org/2102263003 .
diff --git a/mojo/public/cpp/system/tests/BUILD.gn b/mojo/public/cpp/system/tests/BUILD.gn
index fdfe73b..b278180 100644
--- a/mojo/public/cpp/system/tests/BUILD.gn
+++ b/mojo/public/cpp/system/tests/BUILD.gn
@@ -9,7 +9,10 @@
 
   sources = [
     "core_unittest.cc",
+    "data_pipe_unittest.cc",
+    "handle_unittest.cc",
     "macros_unittest.cc",
+    "time_unittest.cc",
   ]
 
   deps = [
diff --git a/mojo/public/cpp/system/tests/core_unittest.cc b/mojo/public/cpp/system/tests/core_unittest.cc
index 05769ca..d0da86b 100644
--- a/mojo/public/cpp/system/tests/core_unittest.cc
+++ b/mojo/public/cpp/system/tests/core_unittest.cc
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <map>
+#include <vector>
 
 #include "mojo/public/cpp/system/buffer.h"
 #include "mojo/public/cpp/system/data_pipe.h"
@@ -22,88 +23,11 @@
 namespace mojo {
 namespace {
 
-TEST(CoreTest, GetTimeTicksNow) {
-  const MojoTimeTicks start = GetTimeTicksNow();
-  EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
-      << "GetTimeTicksNow should return nonzero value";
-}
-
 TEST(CoreTest, Basic) {
-  // Basic |Handle| implementation:
-  {
-    EXPECT_EQ(MOJO_HANDLE_INVALID, kInvalidHandleValue);
-
-    Handle h0;
-    EXPECT_EQ(kInvalidHandleValue, h0.value());
-    EXPECT_EQ(kInvalidHandleValue, *h0.mutable_value());
-    EXPECT_FALSE(h0.is_valid());
-
-    Handle h1(static_cast<MojoHandle>(123));
-    EXPECT_EQ(static_cast<MojoHandle>(123), h1.value());
-    EXPECT_EQ(static_cast<MojoHandle>(123), *h1.mutable_value());
-    EXPECT_TRUE(h1.is_valid());
-    *h1.mutable_value() = static_cast<MojoHandle>(456);
-    EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
-    EXPECT_TRUE(h1.is_valid());
-
-    h1.swap(h0);
-    EXPECT_EQ(static_cast<MojoHandle>(456), h0.value());
-    EXPECT_TRUE(h0.is_valid());
-    EXPECT_FALSE(h1.is_valid());
-
-    h1.set_value(static_cast<MojoHandle>(789));
-    h0.swap(h1);
-    EXPECT_EQ(static_cast<MojoHandle>(789), h0.value());
-    EXPECT_TRUE(h0.is_valid());
-    EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
-    EXPECT_TRUE(h1.is_valid());
-
-    // Make sure copy constructor works.
-    Handle h2(h0);
-    EXPECT_EQ(static_cast<MojoHandle>(789), h2.value());
-    // And assignment.
-    h2 = h1;
-    EXPECT_EQ(static_cast<MojoHandle>(456), h2.value());
-
-    // Make sure that we can put |Handle|s into |std::map|s.
-    h0 = Handle(static_cast<MojoHandle>(987));
-    h1 = Handle(static_cast<MojoHandle>(654));
-    h2 = Handle(static_cast<MojoHandle>(321));
-    Handle h3;
-    std::map<Handle, int> handle_to_int;
-    handle_to_int[h0] = 0;
-    handle_to_int[h1] = 1;
-    handle_to_int[h2] = 2;
-    handle_to_int[h3] = 3;
-
-    EXPECT_EQ(4u, handle_to_int.size());
-    EXPECT_FALSE(handle_to_int.find(h0) == handle_to_int.end());
-    EXPECT_EQ(0, handle_to_int[h0]);
-    EXPECT_FALSE(handle_to_int.find(h1) == handle_to_int.end());
-    EXPECT_EQ(1, handle_to_int[h1]);
-    EXPECT_FALSE(handle_to_int.find(h2) == handle_to_int.end());
-    EXPECT_EQ(2, handle_to_int[h2]);
-    EXPECT_FALSE(handle_to_int.find(h3) == handle_to_int.end());
-    EXPECT_EQ(3, handle_to_int[h3]);
-    EXPECT_TRUE(handle_to_int.find(Handle(static_cast<MojoHandle>(13579))) ==
-                handle_to_int.end());
-
-    // TODO(vtl): With C++11, support |std::unordered_map|s, etc. (Or figure out
-    // how to support the variations of |hash_map|.)
-  }
-
-  // |Handle|/|ScopedHandle| functions:
+  // |Wait|/|WaitMany|:
   {
     ScopedHandle h;
 
-    EXPECT_EQ(kInvalidHandleValue, h.get().value());
-
-    // This should be a no-op.
-    Close(h.Pass());
-
-    // It should still be invalid.
-    EXPECT_EQ(kInvalidHandleValue, h.get().value());
-
     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
               Wait(h.get(), ~MOJO_HANDLE_SIGNAL_NONE, 1000000, nullptr));
 
@@ -128,10 +52,7 @@
 
   // |MakeScopedHandle| (just compilation tests):
   {
-    EXPECT_FALSE(MakeScopedHandle(Handle()).is_valid());
     EXPECT_FALSE(MakeScopedHandle(MessagePipeHandle()).is_valid());
-    EXPECT_FALSE(MakeScopedHandle(DataPipeProducerHandle()).is_valid());
-    EXPECT_FALSE(MakeScopedHandle(DataPipeConsumerHandle()).is_valid());
     EXPECT_FALSE(MakeScopedHandle(SharedBufferHandle()).is_valid());
   }
 
@@ -472,33 +393,6 @@
   }
 }
 
-TEST(CoreTest, ScopedHandleMoveCtor) {
-  ScopedSharedBufferHandle buffer1;
-  EXPECT_EQ(MOJO_RESULT_OK, CreateSharedBuffer(nullptr, 1024, &buffer1));
-  EXPECT_TRUE(buffer1.is_valid());
-
-  ScopedSharedBufferHandle buffer2;
-  EXPECT_EQ(MOJO_RESULT_OK, CreateSharedBuffer(nullptr, 1024, &buffer2));
-  EXPECT_TRUE(buffer2.is_valid());
-
-  // If this fails to close buffer1, ScopedHandleBase::CloseIfNecessary() will
-  // assert.
-  buffer1 = buffer2.Pass();
-
-  EXPECT_TRUE(buffer1.is_valid());
-  EXPECT_FALSE(buffer2.is_valid());
-}
-
-TEST(CoreTest, ScopedHandleMoveCtorSelf) {
-  ScopedSharedBufferHandle buffer1;
-  EXPECT_EQ(MOJO_RESULT_OK, CreateSharedBuffer(nullptr, 1024, &buffer1));
-  EXPECT_TRUE(buffer1.is_valid());
-
-  buffer1 = buffer1.Pass();
-
-  EXPECT_TRUE(buffer1.is_valid());
-}
-
 TEST(CoreTest, WaitManyResult) {
   {
     WaitManyResult wmr(MOJO_RESULT_OK);
@@ -543,104 +437,5 @@
   }
 }
 
-TEST(CoreTest, DataPipe) {
-  ScopedDataPipeProducerHandle ph;
-  ScopedDataPipeConsumerHandle ch;
-
-  ASSERT_EQ(MOJO_RESULT_OK, CreateDataPipe(nullptr, &ph, &ch));
-  ASSERT_TRUE(ph.get().is_valid());
-  ASSERT_TRUE(ch.get().is_valid());
-
-  uint32_t read_threshold = 123u;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            GetDataPipeConsumerOptions(ch.get(), &read_threshold));
-  EXPECT_EQ(0u, read_threshold);
-
-  EXPECT_EQ(MOJO_RESULT_OK, SetDataPipeConsumerOptions(ch.get(), 2u));
-
-  EXPECT_EQ(MOJO_RESULT_OK,
-            GetDataPipeConsumerOptions(ch.get(), &read_threshold));
-  EXPECT_EQ(2u, read_threshold);
-
-  // Write a byte.
-  static const char kA = 'A';
-  uint32_t num_bytes = 1u;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            WriteDataRaw(ph.get(), &kA, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE));
-
-  // Waiting for "read threshold" should fail. (Wait a nonzero amount, in case
-  // there's some latency.)
-  MojoHandleSignalsState state;
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 1000, &state));
-  // ... but it should be readable.
-  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, state.satisfied_signals);
-  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
-                MOJO_HANDLE_SIGNAL_READ_THRESHOLD,
-            state.satisfiable_signals);
-
-  // Do a two-phase write of another byte.
-  void* write_buffer = nullptr;
-  num_bytes = 0u;
-  ASSERT_EQ(MOJO_RESULT_OK,
-            BeginWriteDataRaw(ph.get(), &write_buffer, &num_bytes,
-                              MOJO_WRITE_DATA_FLAG_NONE));
-  ASSERT_TRUE(write_buffer);
-  ASSERT_GT(num_bytes, 0u);
-  static_cast<char*>(write_buffer)[0] = 'B';
-  EXPECT_EQ(MOJO_RESULT_OK, EndWriteDataRaw(ph.get(), 1u));
-
-  // Now waiting for "read threshold" should succeed. (Wait a nonzero amount, in
-  // case there's some latency.)
-  state = MojoHandleSignalsState();
-  EXPECT_EQ(MOJO_RESULT_OK,
-            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 1000, &state));
-  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_READ_THRESHOLD,
-            state.satisfied_signals);
-  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
-                MOJO_HANDLE_SIGNAL_READ_THRESHOLD,
-            state.satisfiable_signals);
-
-  // Read a byte.
-  char read_byte = 'x';
-  num_bytes = 1u;
-  EXPECT_EQ(MOJO_RESULT_OK, ReadDataRaw(ch.get(), &read_byte, &num_bytes,
-                                        MOJO_READ_DATA_FLAG_NONE));
-  EXPECT_EQ(1u, num_bytes);
-  EXPECT_EQ('A', read_byte);
-
-  // Waiting for "read threshold" should now fail.
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 0, nullptr));
-
-  // Reset the read threshold/options.
-  EXPECT_EQ(MOJO_RESULT_OK, SetDataPipeConsumerOptionsToDefault(ch.get()));
-
-  // Waiting for "read threshold" should now succeed.
-  EXPECT_EQ(MOJO_RESULT_OK,
-            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 0, nullptr));
-
-  // Do a two-phase read.
-  const void* read_buffer = nullptr;
-  num_bytes = 0u;
-  ASSERT_EQ(MOJO_RESULT_OK, BeginReadDataRaw(ch.get(), &read_buffer, &num_bytes,
-                                             MOJO_READ_DATA_FLAG_NONE));
-  ASSERT_TRUE(read_buffer);
-  ASSERT_EQ(1u, num_bytes);
-  EXPECT_EQ('B', static_cast<const char*>(read_buffer)[0]);
-  EXPECT_EQ(MOJO_RESULT_OK, EndReadDataRaw(ch.get(), 1u));
-
-  // Waiting for "read" should now fail (time out).
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 1000, nullptr));
-
-  // Close the producer.
-  ph.reset();
-
-  // Waiting for "read" should now fail.
-  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 1000, nullptr));
-}
-
 }  // namespace
 }  // namespace mojo
diff --git a/mojo/public/cpp/system/tests/data_pipe_unittest.cc b/mojo/public/cpp/system/tests/data_pipe_unittest.cc
new file mode 100644
index 0000000..b75eca0
--- /dev/null
+++ b/mojo/public/cpp/system/tests/data_pipe_unittest.cc
@@ -0,0 +1,121 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file tests the C++ wrappers in mojo/public/cpp/system/data_pipe.h.
+
+#include "mojo/public/cpp/system/data_pipe.h"
+
+#include "mojo/public/cpp/system/handle.h"
+#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/cpp/system/wait.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+TEST(DataPipe, Basic) {
+  // Cursory compilation tests of |MakeScopedHandle()| with data pipe handles.
+  EXPECT_FALSE(MakeScopedHandle(DataPipeProducerHandle()).is_valid());
+  EXPECT_FALSE(MakeScopedHandle(DataPipeConsumerHandle()).is_valid());
+
+  ScopedDataPipeProducerHandle ph;
+  ScopedDataPipeConsumerHandle ch;
+
+  ASSERT_EQ(MOJO_RESULT_OK, CreateDataPipe(nullptr, &ph, &ch));
+  ASSERT_TRUE(ph.get().is_valid());
+  ASSERT_TRUE(ch.get().is_valid());
+
+  uint32_t read_threshold = 123u;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            GetDataPipeConsumerOptions(ch.get(), &read_threshold));
+  EXPECT_EQ(0u, read_threshold);
+
+  EXPECT_EQ(MOJO_RESULT_OK, SetDataPipeConsumerOptions(ch.get(), 2u));
+
+  EXPECT_EQ(MOJO_RESULT_OK,
+            GetDataPipeConsumerOptions(ch.get(), &read_threshold));
+  EXPECT_EQ(2u, read_threshold);
+
+  // Write a byte.
+  static const char kA = 'A';
+  uint32_t num_bytes = 1u;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            WriteDataRaw(ph.get(), &kA, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE));
+
+  // Waiting for "read threshold" should fail. (Wait a nonzero amount, in case
+  // there's some latency.)
+  MojoHandleSignalsState state;
+  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
+            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 1000, &state));
+  // ... but it should be readable.
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, state.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
+                MOJO_HANDLE_SIGNAL_READ_THRESHOLD,
+            state.satisfiable_signals);
+
+  // Do a two-phase write of another byte.
+  void* write_buffer = nullptr;
+  num_bytes = 0u;
+  ASSERT_EQ(MOJO_RESULT_OK,
+            BeginWriteDataRaw(ph.get(), &write_buffer, &num_bytes,
+                              MOJO_WRITE_DATA_FLAG_NONE));
+  ASSERT_TRUE(write_buffer);
+  ASSERT_GT(num_bytes, 0u);
+  static_cast<char*>(write_buffer)[0] = 'B';
+  EXPECT_EQ(MOJO_RESULT_OK, EndWriteDataRaw(ph.get(), 1u));
+
+  // Now waiting for "read threshold" should succeed. (Wait a nonzero amount, in
+  // case there's some latency.)
+  state = MojoHandleSignalsState();
+  EXPECT_EQ(MOJO_RESULT_OK,
+            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 1000, &state));
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_READ_THRESHOLD,
+            state.satisfied_signals);
+  EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
+                MOJO_HANDLE_SIGNAL_READ_THRESHOLD,
+            state.satisfiable_signals);
+
+  // Read a byte.
+  char read_byte = 'x';
+  num_bytes = 1u;
+  EXPECT_EQ(MOJO_RESULT_OK, ReadDataRaw(ch.get(), &read_byte, &num_bytes,
+                                        MOJO_READ_DATA_FLAG_NONE));
+  EXPECT_EQ(1u, num_bytes);
+  EXPECT_EQ('A', read_byte);
+
+  // Waiting for "read threshold" should now fail.
+  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
+            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 0, nullptr));
+
+  // Reset the read threshold/options.
+  EXPECT_EQ(MOJO_RESULT_OK, SetDataPipeConsumerOptionsToDefault(ch.get()));
+
+  // Waiting for "read threshold" should now succeed.
+  EXPECT_EQ(MOJO_RESULT_OK,
+            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 0, nullptr));
+
+  // Do a two-phase read.
+  const void* read_buffer = nullptr;
+  num_bytes = 0u;
+  ASSERT_EQ(MOJO_RESULT_OK, BeginReadDataRaw(ch.get(), &read_buffer, &num_bytes,
+                                             MOJO_READ_DATA_FLAG_NONE));
+  ASSERT_TRUE(read_buffer);
+  ASSERT_EQ(1u, num_bytes);
+  EXPECT_EQ('B', static_cast<const char*>(read_buffer)[0]);
+  EXPECT_EQ(MOJO_RESULT_OK, EndReadDataRaw(ch.get(), 1u));
+
+  // Waiting for "read" should now fail (time out).
+  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
+            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 1000, nullptr));
+
+  // Close the producer.
+  ph.reset();
+
+  // Waiting for "read" should now fail.
+  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+            Wait(ch.get(), MOJO_HANDLE_SIGNAL_READ_THRESHOLD, 1000, nullptr));
+}
+
+}  // namespace mojo
+}  // namespace
diff --git a/mojo/public/cpp/system/tests/handle_unittest.cc b/mojo/public/cpp/system/tests/handle_unittest.cc
new file mode 100644
index 0000000..6c40da1
--- /dev/null
+++ b/mojo/public/cpp/system/tests/handle_unittest.cc
@@ -0,0 +1,175 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file tests the C++ wrappers in mojo/public/cpp/system/handle.h.
+
+#include "mojo/public/cpp/system/handle.h"
+
+#include <map>
+#include <utility>
+
+#include "mojo/public/cpp/system/buffer.h"
+#include "mojo/public/cpp/system/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+// Basic |Handle| tests.
+TEST(HandleTest, Handle) {
+  EXPECT_EQ(MOJO_HANDLE_INVALID, kInvalidHandleValue);
+
+  Handle h0;
+  EXPECT_EQ(kInvalidHandleValue, h0.value());
+  EXPECT_EQ(kInvalidHandleValue, *h0.mutable_value());
+  EXPECT_FALSE(h0.is_valid());
+
+  Handle h1(static_cast<MojoHandle>(123));
+  EXPECT_EQ(static_cast<MojoHandle>(123), h1.value());
+  EXPECT_EQ(static_cast<MojoHandle>(123), *h1.mutable_value());
+  EXPECT_TRUE(h1.is_valid());
+  *h1.mutable_value() = static_cast<MojoHandle>(456);
+  EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
+  EXPECT_TRUE(h1.is_valid());
+
+  h1.swap(h0);
+  EXPECT_EQ(static_cast<MojoHandle>(456), h0.value());
+  EXPECT_TRUE(h0.is_valid());
+  EXPECT_FALSE(h1.is_valid());
+
+  h1.set_value(static_cast<MojoHandle>(789));
+  h0.swap(h1);
+  EXPECT_EQ(static_cast<MojoHandle>(789), h0.value());
+  EXPECT_TRUE(h0.is_valid());
+  EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
+  EXPECT_TRUE(h1.is_valid());
+
+  // Make sure copy constructor works.
+  Handle h2(h0);
+  EXPECT_EQ(static_cast<MojoHandle>(789), h2.value());
+  // And assignment.
+  h2 = h1;
+  EXPECT_EQ(static_cast<MojoHandle>(456), h2.value());
+
+  // Make sure that we can put |Handle|s into |std::map|s.
+  h0 = Handle(static_cast<MojoHandle>(987));
+  h1 = Handle(static_cast<MojoHandle>(654));
+  h2 = Handle(static_cast<MojoHandle>(321));
+  Handle h3;
+  std::map<Handle, int> handle_to_int;
+  handle_to_int[h0] = 0;
+  handle_to_int[h1] = 1;
+  handle_to_int[h2] = 2;
+  handle_to_int[h3] = 3;
+
+  EXPECT_EQ(4u, handle_to_int.size());
+  EXPECT_FALSE(handle_to_int.find(h0) == handle_to_int.end());
+  EXPECT_EQ(0, handle_to_int[h0]);
+  EXPECT_FALSE(handle_to_int.find(h1) == handle_to_int.end());
+  EXPECT_EQ(1, handle_to_int[h1]);
+  EXPECT_FALSE(handle_to_int.find(h2) == handle_to_int.end());
+  EXPECT_EQ(2, handle_to_int[h2]);
+  EXPECT_FALSE(handle_to_int.find(h3) == handle_to_int.end());
+  EXPECT_EQ(3, handle_to_int[h3]);
+  EXPECT_TRUE(handle_to_int.find(Handle(static_cast<MojoHandle>(13579))) ==
+              handle_to_int.end());
+
+  // TODO(vtl): With C++11, support |std::unordered_map|s, etc.
+}
+
+// Basic |ScopedHandle| tests.
+TEST(HandleTest, ScopedHandle) {
+  // Invalid |ScopedHandle|:
+  {
+    ScopedHandle sh0;
+
+    EXPECT_EQ(kInvalidHandleValue, sh0.get().value());
+    EXPECT_FALSE(sh0.is_valid());
+
+    // This should be a no-op.
+    Close(sh0.Pass());
+
+    // It should still be invalid.
+    EXPECT_FALSE(sh0.is_valid());
+
+    // Move constructible:
+    ScopedHandle sh1(std::move(sh0));
+    EXPECT_FALSE(sh0.is_valid());
+    EXPECT_FALSE(sh1.is_valid());
+
+    // Move assignable:
+    sh0 = std::move(sh1);
+    EXPECT_FALSE(sh0.is_valid());
+    EXPECT_FALSE(sh1.is_valid());
+  }
+
+  // "Valid" |ScopedHandle| (but note that we can't test that it closes the
+  // handle on leaving scope without having a valid handle!):
+  {
+    Handle h0(static_cast<MojoHandle>(123));
+    ScopedHandle sh0(h0);
+
+    EXPECT_EQ(h0.value(), sh0.get().value());
+    EXPECT_TRUE(sh0.is_valid());
+
+    // Move constructible:
+    ScopedHandle sh1(std::move(sh0));
+    EXPECT_FALSE(sh0.is_valid());
+    EXPECT_TRUE(sh1.is_valid());
+
+    // Move assignable:
+    sh0 = std::move(sh1);
+    EXPECT_TRUE(sh0.is_valid());
+    EXPECT_FALSE(sh1.is_valid());
+
+    // We have to release |sh0|, since it's not really valid.
+    Handle h1 = sh0.release();
+    EXPECT_EQ(h0.value(), h1.value());
+  }
+}
+
+TEST(HandleTest, MakeScopedHandle) {
+  EXPECT_FALSE(MakeScopedHandle(Handle()).is_valid());
+
+  Handle h(static_cast<MojoHandle>(123));
+  auto sh = MakeScopedHandle(h);
+  EXPECT_TRUE(sh.is_valid());
+  EXPECT_EQ(h.value(), sh.get().value());
+  // Have to release |sh0|, since it's not really valid.
+  ignore_result(sh.release());
+}
+
+TEST(HandleTest, ScopedHandleMoveCtor) {
+  // We'll use a shared buffer handle (since we need a valid handle) in a
+  // |ScopedSharedBufferHandle|.
+  ScopedSharedBufferHandle buffer1;
+  EXPECT_EQ(MOJO_RESULT_OK, CreateSharedBuffer(nullptr, 1024, &buffer1));
+  EXPECT_TRUE(buffer1.is_valid());
+
+  ScopedSharedBufferHandle buffer2;
+  EXPECT_EQ(MOJO_RESULT_OK, CreateSharedBuffer(nullptr, 1024, &buffer2));
+  EXPECT_TRUE(buffer2.is_valid());
+
+  // If this fails to close buffer1, ScopedHandleBase::CloseIfNecessary() will
+  // assert.
+  buffer1 = buffer2.Pass();
+
+  EXPECT_TRUE(buffer1.is_valid());
+  EXPECT_FALSE(buffer2.is_valid());
+}
+
+TEST(HandleTest, ScopedHandleMoveCtorSelf) {
+  // We'll use a shared buffer handle (since we need a valid handle) in a
+  // |ScopedSharedBufferHandle|.
+  ScopedSharedBufferHandle buffer1;
+  EXPECT_EQ(MOJO_RESULT_OK, CreateSharedBuffer(nullptr, 1024, &buffer1));
+  EXPECT_TRUE(buffer1.is_valid());
+
+  buffer1 = buffer1.Pass();
+
+  EXPECT_TRUE(buffer1.is_valid());
+}
+
+}  // namespace mojo
+}  // namespace
diff --git a/mojo/public/cpp/system/tests/time_unittest.cc b/mojo/public/cpp/system/tests/time_unittest.cc
new file mode 100644
index 0000000..45c07a7
--- /dev/null
+++ b/mojo/public/cpp/system/tests/time_unittest.cc
@@ -0,0 +1,20 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file tests the C++ wrappers in mojo/public/cpp/system/time.h.
+
+#include "mojo/public/cpp/system/time.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+TEST(TimeTest, GetTimeTicksNow) {
+  const MojoTimeTicks start = GetTimeTicksNow();
+  EXPECT_NE(static_cast<MojoTimeTicks>(0), start);
+}
+
+}  // namespace
+}  // namespace mojo