Implement MojoGetBufferInformation(), part 2.

This adds Core::GetBufferInformation() and hooks it up to Dispatchers.
(But thunks still need to be taken care of.)

Also backfills a bunch of missing testing.

R=vardhan@google.com

Review URL: https://codereview.chromium.org/1781513002 .
diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc
index 4a57e04..f9bcadc 100644
--- a/mojo/edk/system/core.cc
+++ b/mojo/edk/system/core.cc
@@ -518,6 +518,16 @@
   return MOJO_RESULT_OK;
 }
 
+MojoResult Core::GetBufferInformation(MojoHandle buffer_handle,
+                                      UserPointer<MojoBufferInformation> info,
+                                      uint32_t info_num_bytes) {
+  RefPtr<Dispatcher> dispatcher(GetDispatcher(buffer_handle));
+  if (!dispatcher)
+    return MOJO_RESULT_INVALID_ARGUMENT;
+
+  return dispatcher->GetBufferInformation(info, info_num_bytes);
+}
+
 MojoResult Core::MapBuffer(MojoHandle buffer_handle,
                            uint64_t offset,
                            uint64_t num_bytes,
diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h
index 7217888..ab154b1 100644
--- a/mojo/edk/system/core.h
+++ b/mojo/edk/system/core.h
@@ -152,6 +152,9 @@
       MojoHandle buffer_handle,
       UserPointer<const MojoDuplicateBufferHandleOptions> options,
       UserPointer<MojoHandle> new_buffer_handle);
+  MojoResult GetBufferInformation(MojoHandle buffer_handle,
+                                  UserPointer<MojoBufferInformation> info,
+                                  uint32_t info_num_bytes);
   MojoResult MapBuffer(MojoHandle buffer_handle,
                        uint64_t offset,
                        uint64_t num_bytes,
diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc
index 70213da..542eadb 100644
--- a/mojo/edk/system/core_test_base.cc
+++ b/mojo/edk/system/core_test_base.cc
@@ -130,6 +130,33 @@
     return MOJO_RESULT_UNIMPLEMENTED;
   }
 
+  MojoResult DuplicateBufferHandleImplNoLock(
+      UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/,
+      RefPtr<Dispatcher>* /*new_dispatcher*/) override {
+    info_->IncrementDuplicateBufferHandleCallCount();
+    mutex().AssertHeld();
+    return MOJO_RESULT_UNIMPLEMENTED;
+  }
+
+  MojoResult GetBufferInformationImplNoLock(
+      UserPointer<MojoBufferInformation> /*info*/,
+      uint32_t /*info_num_bytes*/) override {
+    info_->IncrementGetBufferInformationCallCount();
+    mutex().AssertHeld();
+    return MOJO_RESULT_UNIMPLEMENTED;
+  }
+
+  MojoResult MapBufferImplNoLock(
+      uint64_t /*offset*/,
+      uint64_t /*num_bytes*/,
+      MojoMapBufferFlags /*flags*/,
+      std::unique_ptr<platform::PlatformSharedBufferMapping>* /*mapping*/)
+      override {
+    info_->IncrementMapBufferCallCount();
+    mutex().AssertHeld();
+    return MOJO_RESULT_UNIMPLEMENTED;
+  }
+
   MojoResult AddAwakableImplNoLock(Awakable* awakable,
                                    MojoHandleSignals /*signals*/,
                                    uint32_t /*context*/,
@@ -197,26 +224,9 @@
 
 // CoreTestBase_MockHandleInfo -------------------------------------------------
 
-CoreTestBase_MockHandleInfo::CoreTestBase_MockHandleInfo()
-    : ctor_call_count_(0),
-      dtor_call_count_(0),
-      close_call_count_(0),
-      write_message_call_count_(0),
-      read_message_call_count_(0),
-      write_data_call_count_(0),
-      begin_write_data_call_count_(0),
-      end_write_data_call_count_(0),
-      read_data_call_count_(0),
-      begin_read_data_call_count_(0),
-      end_read_data_call_count_(0),
-      add_awakable_call_count_(0),
-      remove_awakable_call_count_(0),
-      cancel_all_awakables_call_count_(0),
-      add_awakable_allowed_(false) {
-}
+CoreTestBase_MockHandleInfo::CoreTestBase_MockHandleInfo() {}
 
-CoreTestBase_MockHandleInfo::~CoreTestBase_MockHandleInfo() {
-}
+CoreTestBase_MockHandleInfo::~CoreTestBase_MockHandleInfo() {}
 
 unsigned CoreTestBase_MockHandleInfo::GetCtorCallCount() const {
   MutexLocker locker(&mutex_);
@@ -273,6 +283,22 @@
   return end_read_data_call_count_;
 }
 
+unsigned CoreTestBase_MockHandleInfo::GetDuplicateBufferHandleCallCount()
+    const {
+  MutexLocker locker(&mutex_);
+  return duplicate_buffer_handle_call_count_;
+}
+
+unsigned CoreTestBase_MockHandleInfo::GetGetBufferInformationCallCount() const {
+  MutexLocker locker(&mutex_);
+  return get_buffer_information_call_count_;
+}
+
+unsigned CoreTestBase_MockHandleInfo::GetMapBufferCallCount() const {
+  MutexLocker locker(&mutex_);
+  return map_buffer_call_count_;
+}
+
 unsigned CoreTestBase_MockHandleInfo::GetAddAwakableCallCount() const {
   MutexLocker locker(&mutex_);
   return add_awakable_call_count_;
@@ -353,6 +379,21 @@
   end_read_data_call_count_++;
 }
 
+void CoreTestBase_MockHandleInfo::IncrementDuplicateBufferHandleCallCount() {
+  MutexLocker locker(&mutex_);
+  duplicate_buffer_handle_call_count_++;
+}
+
+void CoreTestBase_MockHandleInfo::IncrementGetBufferInformationCallCount() {
+  MutexLocker locker(&mutex_);
+  get_buffer_information_call_count_++;
+}
+
+void CoreTestBase_MockHandleInfo::IncrementMapBufferCallCount() {
+  MutexLocker locker(&mutex_);
+  map_buffer_call_count_++;
+}
+
 void CoreTestBase_MockHandleInfo::IncrementAddAwakableCallCount() {
   MutexLocker locker(&mutex_);
   add_awakable_call_count_++;
diff --git a/mojo/edk/system/core_test_base.h b/mojo/edk/system/core_test_base.h
index c562ab5..852365e 100644
--- a/mojo/edk/system/core_test_base.h
+++ b/mojo/edk/system/core_test_base.h
@@ -67,6 +67,9 @@
   unsigned GetReadDataCallCount() const;
   unsigned GetBeginReadDataCallCount() const;
   unsigned GetEndReadDataCallCount() const;
+  unsigned GetDuplicateBufferHandleCallCount() const;
+  unsigned GetGetBufferInformationCallCount() const;
+  unsigned GetMapBufferCallCount() const;
   unsigned GetAddAwakableCallCount() const;
   unsigned GetRemoveAwakableCallCount() const;
   unsigned GetCancelAllAwakablesCallCount() const;
@@ -86,6 +89,9 @@
   void IncrementReadDataCallCount();
   void IncrementBeginReadDataCallCount();
   void IncrementEndReadDataCallCount();
+  void IncrementDuplicateBufferHandleCallCount();
+  void IncrementGetBufferInformationCallCount();
+  void IncrementMapBufferCallCount();
   void IncrementAddAwakableCallCount();
   void IncrementRemoveAwakableCallCount();
   void IncrementCancelAllAwakablesCallCount();
@@ -96,22 +102,25 @@
 
  private:
   mutable util::Mutex mutex_;
-  unsigned ctor_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned dtor_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned close_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned write_message_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned read_message_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned write_data_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned begin_write_data_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned end_write_data_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned read_data_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned begin_read_data_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned end_read_data_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned add_awakable_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned remove_awakable_call_count_ MOJO_GUARDED_BY(mutex_);
-  unsigned cancel_all_awakables_call_count_ MOJO_GUARDED_BY(mutex_);
+  unsigned ctor_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned dtor_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned close_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned write_message_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned read_message_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned write_data_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned begin_write_data_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned end_write_data_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned read_data_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned begin_read_data_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned end_read_data_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned duplicate_buffer_handle_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned get_buffer_information_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned map_buffer_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned add_awakable_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned remove_awakable_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
+  unsigned cancel_all_awakables_call_count_ MOJO_GUARDED_BY(mutex_) = 0;
 
-  bool add_awakable_allowed_ MOJO_GUARDED_BY(mutex_);
+  bool add_awakable_allowed_ MOJO_GUARDED_BY(mutex_) = false;
   std::vector<Awakable*> added_awakables_ MOJO_GUARDED_BY(mutex_);
 
   MOJO_DISALLOW_COPY_AND_ASSIGN(CoreTestBase_MockHandleInfo);
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc
index 268aadb..ead68e6 100644
--- a/mojo/edk/system/core_unittest.cc
+++ b/mojo/edk/system/core_unittest.cc
@@ -99,6 +99,23 @@
   EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, core()->EndReadData(h, 0));
   EXPECT_EQ(1u, info.GetEndReadDataCallCount());
 
+  EXPECT_EQ(0u, info.GetDuplicateBufferHandleCallCount());
+  EXPECT_EQ(
+      MOJO_RESULT_UNIMPLEMENTED,
+      core()->DuplicateBufferHandle(h, NullUserPointer(), NullUserPointer()));
+  EXPECT_EQ(1u, info.GetDuplicateBufferHandleCallCount());
+
+  EXPECT_EQ(0u, info.GetGetBufferInformationCallCount());
+  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
+            core()->GetBufferInformation(h, NullUserPointer(), 0));
+  EXPECT_EQ(1u, info.GetGetBufferInformationCallCount());
+
+  EXPECT_EQ(0u, info.GetMapBufferCallCount());
+  EXPECT_EQ(
+      MOJO_RESULT_UNIMPLEMENTED,
+      core()->MapBuffer(h, 0, 0, NullUserPointer(), MOJO_MAP_BUFFER_FLAG_NONE));
+  EXPECT_EQ(1u, info.GetMapBufferCallCount());
+
   EXPECT_EQ(0u, info.GetAddAwakableCallCount());
   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
             core()->Wait(h, ~MOJO_HANDLE_SIGNAL_NONE, MOJO_DEADLINE_INDEFINITE,
@@ -320,8 +337,20 @@
     EXPECT_EQ(MOJO_RESULT_OK, core()->Close(handles[1]));
   }
 
-  // |CreateMessagePipe()|: Nothing to check (apart from things that cause
-  // death).
+  // |CreateMessagePipe()|:
+  {
+    // Invalid options: unknown flag.
+    const MojoCreateMessagePipeOptions kOptions = {
+        static_cast<uint32_t>(sizeof(MojoCreateMessagePipeOptions)),
+        ~MOJO_CREATE_MESSAGE_PIPE_OPTIONS_FLAG_NONE};
+    MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID};
+    EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
+              core()->CreateMessagePipe(MakeUserPointer(&kOptions),
+                                        MakeUserPointer(&handles[0]),
+                                        MakeUserPointer(&handles[1])));
+    EXPECT_EQ(MOJO_HANDLE_INVALID, handles[0]);
+    EXPECT_EQ(MOJO_HANDLE_INVALID, handles[1]);
+  }
 
   // |WriteMessage()|:
   // Only check arguments checked by |Core|, namely |handle|, |handles|, and
@@ -443,6 +472,82 @@
 
     EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
   }
+
+  // |CreateDataPipe()|:
+  {
+    // Invalid options: unknown flag.
+    const MojoCreateDataPipeOptions kOptions = {
+        static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)),
+        ~MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1u, 0u};
+    MojoHandle handles[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID};
+    EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
+              core()->CreateDataPipe(MakeUserPointer(&kOptions),
+                                     MakeUserPointer(&handles[0]),
+                                     MakeUserPointer(&handles[1])));
+    EXPECT_EQ(MOJO_HANDLE_INVALID, handles[0]);
+    EXPECT_EQ(MOJO_HANDLE_INVALID, handles[1]);
+  }
+
+  // |WriteData()|:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            core()->WriteData(MOJO_HANDLE_INVALID, NullUserPointer(),
+                              NullUserPointer(), MOJO_WRITE_DATA_FLAG_NONE));
+
+  // |BeginWriteData()|:
+  EXPECT_EQ(
+      MOJO_RESULT_INVALID_ARGUMENT,
+      core()->BeginWriteData(MOJO_HANDLE_INVALID, NullUserPointer(),
+                             NullUserPointer(), MOJO_WRITE_DATA_FLAG_NONE));
+
+  // |EndWriteData()|:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            core()->EndWriteData(MOJO_HANDLE_INVALID, 0u));
+
+  // |ReadData()|:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            core()->ReadData(MOJO_HANDLE_INVALID, NullUserPointer(),
+                             NullUserPointer(), MOJO_READ_DATA_FLAG_NONE));
+
+  // |BeginReadData()|:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            core()->BeginReadData(MOJO_HANDLE_INVALID, NullUserPointer(),
+                                  NullUserPointer(), MOJO_READ_DATA_FLAG_NONE));
+
+  // |EndReadData()|:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            core()->EndReadData(MOJO_HANDLE_INVALID, 0u));
+
+  // |CreateSharedBuffer()|:
+  {
+    // Invalid options: unknown flag.
+    const MojoCreateSharedBufferOptions kOptions = {
+        static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)),
+        ~MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE};
+    MojoHandle handle = MOJO_HANDLE_INVALID;
+    EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED,
+              core()->CreateSharedBuffer(MakeUserPointer(&kOptions), 4096u,
+                                         MakeUserPointer(&handle)));
+    EXPECT_EQ(MOJO_HANDLE_INVALID, handle);
+  }
+
+  // |DuplicateBufferHandle()|:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            core()->DuplicateBufferHandle(
+                MOJO_HANDLE_INVALID, NullUserPointer(), NullUserPointer()));
+
+  // |GetBufferInformation()|:
+  EXPECT_EQ(
+      MOJO_RESULT_INVALID_ARGUMENT,
+      core()->GetBufferInformation(MOJO_HANDLE_INVALID, NullUserPointer(), 0u));
+
+  // |MapBuffer()|:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            core()->MapBuffer(MOJO_HANDLE_INVALID, 0u, 0u, NullUserPointer(),
+                              MOJO_MAP_BUFFER_FLAG_NONE));
+
+  // |UnmapBuffer()|:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            core()->UnmapBuffer(NullUserPointer()));
 }
 
 // These test invalid arguments that should cause death if we're being paranoid
@@ -521,6 +626,8 @@
 
     EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h));
   }
+
+  // TODO(vtl): Missing a bunch here.
 }
 
 // TODO(vtl): test |Wait()| and |WaitMany()| properly