diff options
author | amistry <amistry@chromium.org> | 2016-02-11 04:07:00 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-11 12:08:26 +0000 |
commit | 78ceecffbe6dd93b0f27e7b35342fd576bbc66e7 (patch) | |
tree | be9877567dad835a2d8b32d877e86b500d62e17f /mojo | |
parent | 014d75d0a8a332d391b230b917be7592693c5204 (diff) | |
download | chromium_src-78ceecffbe6dd93b0f27e7b35342fd576bbc66e7.zip chromium_src-78ceecffbe6dd93b0f27e7b35342fd576bbc66e7.tar.gz chromium_src-78ceecffbe6dd93b0f27e7b35342fd576bbc66e7.tar.bz2 |
Add a Mojo embedder API that wraps a base::SharedMemoryHandle into a Mojo shared buffer handle.
BUG=582993
Review URL: https://codereview.chromium.org/1689063002
Cr-Commit-Position: refs/heads/master@{#374885}
Diffstat (limited to 'mojo')
-rw-r--r-- | mojo/edk/embedder/embedder.cc | 9 | ||||
-rw-r--r-- | mojo/edk/embedder/embedder.h | 14 | ||||
-rw-r--r-- | mojo/edk/embedder/embedder_unittest.cc | 85 | ||||
-rw-r--r-- | mojo/edk/embedder/platform_support.h | 5 | ||||
-rw-r--r-- | mojo/edk/embedder/simple_platform_shared_buffer.cc | 28 | ||||
-rw-r--r-- | mojo/edk/embedder/simple_platform_shared_buffer.h | 8 | ||||
-rw-r--r-- | mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc | 34 | ||||
-rw-r--r-- | mojo/edk/embedder/simple_platform_support.cc | 9 | ||||
-rw-r--r-- | mojo/edk/embedder/simple_platform_support.h | 4 | ||||
-rw-r--r-- | mojo/edk/system/core.cc | 25 | ||||
-rw-r--r-- | mojo/edk/system/core.h | 8 | ||||
-rw-r--r-- | mojo/edk/system/shared_buffer_dispatcher.cc | 11 | ||||
-rw-r--r-- | mojo/edk/system/shared_buffer_dispatcher.h | 5 | ||||
-rw-r--r-- | mojo/edk/system/shared_buffer_dispatcher_unittest.cc | 37 |
14 files changed, 281 insertions, 1 deletions
diff --git a/mojo/edk/embedder/embedder.cc b/mojo/edk/embedder/embedder.cc index 37c3ddc..0ed4b4c 100644 --- a/mojo/edk/embedder/embedder.cc +++ b/mojo/edk/embedder/embedder.cc @@ -81,6 +81,15 @@ MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, platform_handle_wrapper_handle, platform_handle); } +MojoResult CreateSharedBufferWrapper( + base::SharedMemoryHandle shared_memory_handle, + size_t num_bytes, + bool read_only, + MojoHandle* mojo_wrapper_handle) { + return internal::g_core->CreateSharedBufferWrapper( + shared_memory_handle, num_bytes, read_only, mojo_wrapper_handle); +} + void InitIPCSupport(ProcessDelegate* process_delegate, scoped_refptr<base::TaskRunner> io_thread_task_runner) { CHECK(internal::g_core); diff --git a/mojo/edk/embedder/embedder.h b/mojo/edk/embedder/embedder.h index 1adbc79..6c010f4 100644 --- a/mojo/edk/embedder/embedder.h +++ b/mojo/edk/embedder/embedder.h @@ -13,6 +13,7 @@ #include "base/command_line.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/shared_memory_handle.h" #include "base/process/process_handle.h" #include "base/task_runner.h" #include "mojo/edk/embedder/scoped_platform_handle.h" @@ -80,6 +81,19 @@ MOJO_SYSTEM_IMPL_EXPORT MojoResult PassWrappedPlatformHandle(MojoHandle platform_handle_wrapper_handle, ScopedPlatformHandle* platform_handle); +// Creates a |MojoHandle| that wraps the given |SharedMemoryHandle| (taking +// ownership of it). |num_bytes| is the size of the shared memory object, and +// |read_only| is whether the handle is a read-only handle to shared memory. +// This |MojoHandle| is a Mojo shared buffer and can be manipulated using the +// shared buffer functions and transferred over a message pipe. +// TODO(crbug.com/556587): Support read-only handles. Currently, |read_only| +// must be false. +MOJO_SYSTEM_IMPL_EXPORT MojoResult +CreateSharedBufferWrapper(base::SharedMemoryHandle shared_memory_handle, + size_t num_bytes, + bool read_only, + MojoHandle* mojo_wrapper_handle); + // Initialialization/shutdown for interprocess communication (IPC) ------------- // |InitIPCSupport()| sets up the subsystem for interprocess communication, diff --git a/mojo/edk/embedder/embedder_unittest.cc b/mojo/edk/embedder/embedder_unittest.cc index 86cfc5b..10d3677b 100644 --- a/mojo/edk/embedder/embedder_unittest.cc +++ b/mojo/edk/embedder/embedder_unittest.cc @@ -6,16 +6,17 @@ #include <stddef.h> #include <stdint.h> +#include <string.h> #include <utility> #include "base/bind.h" #include "base/command_line.h" #include "base/logging.h" +#include "base/memory/shared_memory.h" #include "base/message_loop/message_loop.h" #include "base/synchronization/waitable_event.h" #include "base/test/test_timeouts.h" -#include "mojo/edk/embedder/embedder.h" #include "mojo/edk/embedder/platform_channel_pair.h" #include "mojo/edk/embedder/simple_platform_support.h" #include "mojo/edk/embedder/test_embedder.h" @@ -39,6 +40,12 @@ const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED; +// The multiprocess tests that use these don't compile on iOS. +#if !defined(OS_IOS) +const char kHelloWorld[] = "hello world"; +const char kByeWorld[] = "bye world"; +#endif + using EmbedderTest = test::MojoTestBase; TEST_F(EmbedderTest, ChannelBasic) { @@ -284,6 +291,82 @@ DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessChannelsClient, EmbedderTest, ASSERT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); } +#if defined(OS_ANDROID) +// Android multi-process tests are not executing the new process. This is flaky. +#define MAYBE_MultiprocessBaseSharedMemory DISABLED_MultiprocessBaseSharedMemory +#else +#define MAYBE_MultiprocessBaseSharedMemory MultiprocessBaseSharedMemory +#endif // defined(OS_ANDROID) +TEST_F(EmbedderTest, MAYBE_MultiprocessBaseSharedMemory) { + RUN_CHILD_ON_PIPE(MultiprocessSharedMemoryClient, server_mp) + // 1. Create a base::SharedMemory object and create a mojo shared buffer + // from it. + base::SharedMemoryCreateOptions options; + options.size = 123; +#if defined(OS_MACOSX) && !defined(OS_IOS) + options.type = base::SharedMemoryHandle::POSIX; +#endif + base::SharedMemory shared_memory; + ASSERT_TRUE(shared_memory.Create(options)); + base::SharedMemoryHandle shm_handle = base::SharedMemory::DuplicateHandle( + shared_memory.handle()); + MojoHandle sb1; + ASSERT_EQ(MOJO_RESULT_OK, + CreateSharedBufferWrapper(shm_handle, 123, false, &sb1)); + + // 2. Map |sb1| and write something into it. + char* buffer = nullptr; + ASSERT_EQ(MOJO_RESULT_OK, + MojoMapBuffer(sb1, 0, 123, reinterpret_cast<void**>(&buffer), 0)); + ASSERT_TRUE(buffer); + memcpy(buffer, kHelloWorld, sizeof(kHelloWorld)); + + // 3. Duplicate |sb1| into |sb2| and pass to |server_mp|. + MojoHandle sb2 = MOJO_HANDLE_INVALID; + EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(sb1, 0, &sb2)); + EXPECT_NE(MOJO_HANDLE_INVALID, sb2); + WriteMessageWithHandles(server_mp, "hello", &sb2, 1); + + // 4. Read a message from |server_mp|. + EXPECT_EQ("bye", ReadMessage(server_mp)); + + // 5. Expect that the contents of the shared buffer have changed. + EXPECT_EQ(kByeWorld, std::string(buffer)); + + // 6. Map the original base::SharedMemory and expect it contains the + // expected value. + ASSERT_TRUE(shared_memory.Map(123)); + EXPECT_EQ(kByeWorld, + std::string(static_cast<char*>(shared_memory.memory()))); + + ASSERT_EQ(MOJO_RESULT_OK, MojoClose(sb1)); + END_CHILD() +} + +DEFINE_TEST_CLIENT_TEST_WITH_PIPE(MultiprocessSharedMemoryClient, EmbedderTest, + client_mp) { + // 1. Read the first message from |client_mp|, which should have |sb1| which + // should be a shared buffer handle. + MojoHandle sb1; + EXPECT_EQ("hello", ReadMessageWithHandles(client_mp, &sb1, 1)); + + // 2. Map |sb1|. + char* buffer = nullptr; + ASSERT_EQ(MOJO_RESULT_OK, + MojoMapBuffer(sb1, 0, 123, reinterpret_cast<void**>(&buffer), 0)); + ASSERT_TRUE(buffer); + + // 3. Ensure |buffer| contains the values we expect. + EXPECT_EQ(kHelloWorld, std::string(buffer)); + + // 4. Write into |buffer| and send a message back. + memcpy(buffer, kByeWorld, sizeof(kByeWorld)); + WriteMessage(client_mp, "bye"); + + // 5. Close |sb1|. + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(sb1)); +} + // TODO(vtl): Test immediate write & close. // TODO(vtl): Test broken-connection cases. diff --git a/mojo/edk/embedder/platform_support.h b/mojo/edk/embedder/platform_support.h index 160ba79..bc11289 100644 --- a/mojo/edk/embedder/platform_support.h +++ b/mojo/edk/embedder/platform_support.h @@ -7,6 +7,7 @@ #include <stddef.h> +#include "base/memory/shared_memory_handle.h" #include "mojo/edk/embedder/scoped_platform_handle.h" #include "mojo/edk/system/system_impl_export.h" #include "mojo/public/cpp/system/macros.h" @@ -29,6 +30,10 @@ class MOJO_SYSTEM_IMPL_EXPORT PlatformSupport { virtual PlatformSharedBuffer* CreateSharedBufferFromHandle( size_t num_bytes, ScopedPlatformHandle platform_handle) = 0; + virtual PlatformSharedBuffer* CreateSharedBufferFromSharedMemoryHandle( + size_t num_bytes, + bool read_only, + base::SharedMemoryHandle handle) = 0; protected: PlatformSupport() {} diff --git a/mojo/edk/embedder/simple_platform_shared_buffer.cc b/mojo/edk/embedder/simple_platform_shared_buffer.cc index caa926c..5a18131 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer.cc +++ b/mojo/edk/embedder/simple_platform_shared_buffer.cc @@ -69,6 +69,21 @@ SimplePlatformSharedBuffer::CreateFromPlatformHandle( return rv; } +// static +SimplePlatformSharedBuffer* +SimplePlatformSharedBuffer::CreateFromSharedMemoryHandle( + size_t num_bytes, + bool read_only, + base::SharedMemoryHandle handle) { + DCHECK_GT(num_bytes, 0u); + DCHECK(!read_only); + + SimplePlatformSharedBuffer* rv = new SimplePlatformSharedBuffer(num_bytes); + rv->InitFromSharedMemoryHandle(handle); + + return rv; +} + size_t SimplePlatformSharedBuffer::GetNumBytes() const { return num_bytes_; } @@ -176,6 +191,19 @@ bool SimplePlatformSharedBuffer::InitFromPlatformHandle( return true; } +void SimplePlatformSharedBuffer::InitFromSharedMemoryHandle( + base::SharedMemoryHandle handle) { + DCHECK(!shared_memory_); + +#if defined(OS_MACOSX) && !defined(OS_IOS) + // TODO(crbug.com/582468): Support Mach shared memory. + CHECK(handle.GetType() == base::SharedMemoryHandle::POSIX); +#endif + + // TODO(crbug.com/556587): Support read-only handles. + shared_memory_.reset(new base::SharedMemory(handle, false)); +} + SimplePlatformSharedBufferMapping::~SimplePlatformSharedBufferMapping() { Unmap(); } diff --git a/mojo/edk/embedder/simple_platform_shared_buffer.h b/mojo/edk/embedder/simple_platform_shared_buffer.h index 068f668..0f68bc2 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer.h +++ b/mojo/edk/embedder/simple_platform_shared_buffer.h @@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/shared_memory.h" +#include "base/memory/shared_memory_handle.h" #include "base/synchronization/lock.h" #include "mojo/edk/embedder/platform_shared_buffer.h" #include "mojo/edk/system/system_impl_export.h" @@ -30,6 +31,11 @@ class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBuffer final size_t num_bytes, ScopedPlatformHandle platform_handle); + static SimplePlatformSharedBuffer* CreateFromSharedMemoryHandle( + size_t num_bytes, + bool read_only, + base::SharedMemoryHandle handle); + // |PlatformSharedBuffer| implementation: size_t GetNumBytes() const override; scoped_ptr<PlatformSharedBufferMapping> Map(size_t offset, @@ -52,6 +58,8 @@ class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSharedBuffer final // claimed |num_bytes_|.) bool InitFromPlatformHandle(ScopedPlatformHandle platform_handle); + void InitFromSharedMemoryHandle(base::SharedMemoryHandle handle); + const size_t num_bytes_; base::Lock lock_; diff --git a/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc b/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc index 4924372..99bfa6e 100644 --- a/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc +++ b/mojo/edk/embedder/simple_platform_shared_buffer_unittest.cc @@ -10,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/shared_memory.h" #include "base/sys_info.h" #include "mojo/public/cpp/system/macros.h" #include "testing/gtest/include/gtest/gtest.h" @@ -192,6 +193,39 @@ TEST(SimplePlatformSharedBufferTest, MappingsOutliveBuffer) { EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]); } +TEST(SimplePlatformSharedBufferTest, FromSharedMemoryHandle) { + const size_t kBufferSize = 1234; + base::SharedMemoryCreateOptions options; + options.size = kBufferSize; +#if defined(OS_MACOSX) && !defined(OS_IOS) + options.type = base::SharedMemoryHandle::POSIX; +#endif + base::SharedMemory shared_memory; + ASSERT_TRUE(shared_memory.Create(options)); + ASSERT_TRUE(shared_memory.Map(kBufferSize)); + + base::SharedMemoryHandle shm_handle = + base::SharedMemory::DuplicateHandle(shared_memory.handle()); + scoped_refptr<SimplePlatformSharedBuffer> simple_buffer( + SimplePlatformSharedBuffer::CreateFromSharedMemoryHandle( + kBufferSize, false /* read_only */, shm_handle)); + ASSERT_TRUE(simple_buffer); + + scoped_ptr<PlatformSharedBufferMapping> mapping = + simple_buffer->Map(0, kBufferSize); + ASSERT_TRUE(mapping); + + const int kOffset = 123; + char* base_memory = static_cast<char*>(shared_memory.memory()); + char* mojo_memory = static_cast<char*>(mapping->GetBase()); + base_memory[kOffset] = 0; + EXPECT_EQ(0, mojo_memory[kOffset]); + base_memory[kOffset] = 'a'; + EXPECT_EQ('a', mojo_memory[kOffset]); + mojo_memory[kOffset] = 'z'; + EXPECT_EQ('z', base_memory[kOffset]); +} + } // namespace } // namespace edk } // namespace mojo diff --git a/mojo/edk/embedder/simple_platform_support.cc b/mojo/edk/embedder/simple_platform_support.cc index b377bf2..6c2de1a 100644 --- a/mojo/edk/embedder/simple_platform_support.cc +++ b/mojo/edk/embedder/simple_platform_support.cc @@ -31,5 +31,14 @@ PlatformSharedBuffer* SimplePlatformSupport::CreateSharedBufferFromHandle( num_bytes, std::move(platform_handle)); } +PlatformSharedBuffer* +SimplePlatformSupport::CreateSharedBufferFromSharedMemoryHandle( + size_t num_bytes, + bool read_only, + base::SharedMemoryHandle handle) { + return SimplePlatformSharedBuffer::CreateFromSharedMemoryHandle( + num_bytes, read_only, handle); +} + } // namespace edk } // namespace mojo diff --git a/mojo/edk/embedder/simple_platform_support.h b/mojo/edk/embedder/simple_platform_support.h index 0c00098..d79e8ff 100644 --- a/mojo/edk/embedder/simple_platform_support.h +++ b/mojo/edk/embedder/simple_platform_support.h @@ -30,6 +30,10 @@ class MOJO_SYSTEM_IMPL_EXPORT SimplePlatformSupport final PlatformSharedBuffer* CreateSharedBufferFromHandle( size_t num_bytes, ScopedPlatformHandle platform_handle) override; + PlatformSharedBuffer* CreateSharedBufferFromSharedMemoryHandle( + size_t num_bytes, + bool read_only, + base::SharedMemoryHandle handle) override; private: MOJO_DISALLOW_COPY_AND_ASSIGN(SimplePlatformSupport); diff --git a/mojo/edk/system/core.cc b/mojo/edk/system/core.cc index d0b7b67..079faec 100644 --- a/mojo/edk/system/core.cc +++ b/mojo/edk/system/core.cc @@ -138,6 +138,31 @@ MojoResult Core::PassWrappedPlatformHandle( return MOJO_RESULT_OK; } +MojoResult Core::CreateSharedBufferWrapper( + base::SharedMemoryHandle shared_memory_handle, + size_t num_bytes, + bool read_only, + MojoHandle* mojo_wrapper_handle) { + DCHECK(num_bytes); + CHECK(!read_only); + scoped_refptr<PlatformSharedBuffer> platform_buffer = + internal::g_platform_support->CreateSharedBufferFromSharedMemoryHandle( + num_bytes, read_only, shared_memory_handle); + if (!platform_buffer) + return MOJO_RESULT_UNKNOWN; + + scoped_refptr<SharedBufferDispatcher> dispatcher; + MojoResult result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer( + platform_buffer, &dispatcher); + if (result != MOJO_RESULT_OK) + return result; + MojoHandle h = AddDispatcher(dispatcher); + if (h == MOJO_HANDLE_INVALID) + return MOJO_RESULT_RESOURCE_EXHAUSTED; + *mojo_wrapper_handle = h; + return MOJO_RESULT_OK; +} + void Core::RequestShutdown(const base::Closure& callback) { base::Closure on_shutdown; if (base::ThreadTaskRunnerHandle::IsSet()) { diff --git a/mojo/edk/system/core.h b/mojo/edk/system/core.h index 603cba9..0e08a8c 100644 --- a/mojo/edk/system/core.h +++ b/mojo/edk/system/core.h @@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/shared_memory_handle.h" #include "base/synchronization/lock.h" #include "base/task_runner.h" #include "mojo/edk/embedder/scoped_platform_handle.h" @@ -74,12 +75,19 @@ class MOJO_SYSTEM_IMPL_EXPORT Core { const std::vector<Dispatcher::DispatcherInTransit>& dispatchers, MojoHandle* handles); + // See "mojo/edk/embedder/embedder.h" for more information on these functions. MojoResult CreatePlatformHandleWrapper(ScopedPlatformHandle platform_handle, MojoHandle* wrapper_handle); MojoResult PassWrappedPlatformHandle(MojoHandle wrapper_handle, ScopedPlatformHandle* platform_handle); + MojoResult CreateSharedBufferWrapper( + base::SharedMemoryHandle shared_memory_handle, + size_t num_bytes, + bool read_only, + MojoHandle* mojo_wrapper_handle); + // Requests that the EDK tear itself down. |callback| will be called once // the shutdown process is complete. Note that |callback| is always called // asynchronously on the calling thread if said thread is running a message diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc index 94b3d28..8b3971f 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.cc +++ b/mojo/edk/system/shared_buffer_dispatcher.cc @@ -84,6 +84,17 @@ MojoResult SharedBufferDispatcher::Create( } // static +MojoResult SharedBufferDispatcher::CreateFromPlatformSharedBuffer( + const scoped_refptr<PlatformSharedBuffer>& shared_buffer, + scoped_refptr<SharedBufferDispatcher>* result) { + if (!shared_buffer) + return MOJO_RESULT_INVALID_ARGUMENT; + + *result = CreateInternal(shared_buffer); + return MOJO_RESULT_OK; +} + +// static scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( const void* bytes, size_t num_bytes, diff --git a/mojo/edk/system/shared_buffer_dispatcher.h b/mojo/edk/system/shared_buffer_dispatcher.h index e8b6420..75c31b8 100644 --- a/mojo/edk/system/shared_buffer_dispatcher.h +++ b/mojo/edk/system/shared_buffer_dispatcher.h @@ -48,6 +48,11 @@ class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher final : public Dispatcher { uint64_t num_bytes, scoped_refptr<SharedBufferDispatcher>* result); + // Create a |SharedBufferDispatcher| from |shared_buffer|. + static MojoResult CreateFromPlatformSharedBuffer( + const scoped_refptr<PlatformSharedBuffer>& shared_buffer, + scoped_refptr<SharedBufferDispatcher>* result); + // The "opposite" of SerializeAndClose(). Called by Dispatcher::Deserialize(). static scoped_refptr<SharedBufferDispatcher> Deserialize( const void* bytes, diff --git a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc index 7ce119c..f3774fa 100644 --- a/mojo/edk/system/shared_buffer_dispatcher_unittest.cc +++ b/mojo/edk/system/shared_buffer_dispatcher_unittest.cc @@ -150,6 +150,43 @@ TEST_F(SharedBufferDispatcherTest, CreateAndMapBuffer) { EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]); } +TEST_F(SharedBufferDispatcherTest, CreateAndMapBufferFromPlatformBuffer) { + scoped_refptr<PlatformSharedBuffer> platform_shared_buffer = + platform_support()->CreateSharedBuffer(100); + ASSERT_TRUE(platform_shared_buffer); + scoped_refptr<SharedBufferDispatcher> dispatcher; + EXPECT_EQ(MOJO_RESULT_OK, + SharedBufferDispatcher::CreateFromPlatformSharedBuffer( + platform_shared_buffer, &dispatcher)); + ASSERT_TRUE(dispatcher); + EXPECT_EQ(Dispatcher::Type::SHARED_BUFFER, dispatcher->GetType()); + + // Make a couple of mappings. + scoped_ptr<PlatformSharedBufferMapping> mapping1; + EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( + 0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping1)); + ASSERT_TRUE(mapping1); + ASSERT_TRUE(mapping1->GetBase()); + EXPECT_EQ(100u, mapping1->GetLength()); + // Write something. + static_cast<char*>(mapping1->GetBase())[50] = 'x'; + + scoped_ptr<PlatformSharedBufferMapping> mapping2; + EXPECT_EQ(MOJO_RESULT_OK, dispatcher->MapBuffer( + 50, 50, MOJO_MAP_BUFFER_FLAG_NONE, &mapping2)); + ASSERT_TRUE(mapping2); + ASSERT_TRUE(mapping2->GetBase()); + EXPECT_EQ(50u, mapping2->GetLength()); + EXPECT_EQ('x', static_cast<char*>(mapping2->GetBase())[0]); + + EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close()); + + // Check that we can still read/write to mappings after the dispatcher has + // gone away. + static_cast<char*>(mapping2->GetBase())[1] = 'y'; + EXPECT_EQ('y', static_cast<char*>(mapping1->GetBase())[51]); +} + TEST_F(SharedBufferDispatcherTest, DuplicateBufferHandle) { scoped_refptr<SharedBufferDispatcher> dispatcher1; EXPECT_EQ(MOJO_RESULT_OK, SharedBufferDispatcher::Create( |