Index: mojo/system/multiprocess_message_pipe_unittest.cc |
diff --git a/mojo/system/multiprocess_message_pipe_unittest.cc b/mojo/system/multiprocess_message_pipe_unittest.cc |
index beaa38a3b5759530f03c5515f742e3f5966fd8ae..0e2e44502053583bc2de2b58165e2770a09f4cc5 100644 |
--- a/mojo/system/multiprocess_message_pipe_unittest.cc |
+++ b/mojo/system/multiprocess_message_pipe_unittest.cc |
@@ -4,6 +4,7 @@ |
#include <stdint.h> |
#include <stdio.h> |
+#include <string.h> |
#include <string> |
#include <vector> |
@@ -27,6 +28,8 @@ |
#include "mojo/system/platform_handle_dispatcher.h" |
#include "mojo/system/proxy_message_pipe_endpoint.h" |
#include "mojo/system/raw_channel.h" |
+#include "mojo/system/raw_shared_buffer.h" |
+#include "mojo/system/shared_buffer_dispatcher.h" |
#include "mojo/system/test_utils.h" |
#include "mojo/system/waiter.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -280,6 +283,176 @@ TEST_F(MultiprocessMessagePipeTest, QueueMessages) { |
helper()->WaitForChildShutdown()); |
} |
+MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { |
+ ChannelThread channel_thread; |
+ embedder::ScopedPlatformHandle client_platform_handle = |
+ mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); |
+ CHECK(client_platform_handle.is_valid()); |
+ scoped_refptr<MessagePipe> mp(new MessagePipe( |
+ scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
+ scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
+ channel_thread.Start(client_platform_handle.Pass(), mp); |
+ |
+ // Wait for the first message from our parent. |
+ CHECK_EQ(WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE), MOJO_RESULT_OK); |
+ |
+ // It should have a shared buffer. |
+ std::string read_buffer(100, '\0'); |
+ uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |
+ DispatcherVector dispatchers; |
+ uint32_t num_dispatchers = 10; // Maximum number to receive. |
+ CHECK_EQ(mp->ReadMessage(0, |
+ &read_buffer[0], &num_bytes, |
+ &dispatchers, &num_dispatchers, |
+ MOJO_READ_MESSAGE_FLAG_NONE), |
+ MOJO_RESULT_OK); |
+ read_buffer.resize(num_bytes); |
+ CHECK_EQ(read_buffer, std::string("go 1")); |
+ CHECK_EQ(num_dispatchers, 1u); |
+ |
+ CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::kTypeSharedBuffer); |
+ |
+ scoped_refptr<SharedBufferDispatcher> dispatcher( |
+ static_cast<SharedBufferDispatcher*>(dispatchers[0].get())); |
+ |
+ // Make a mapping. |
+ scoped_ptr<RawSharedBufferMapping> mapping; |
+ CHECK_EQ(dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping), |
+ MOJO_RESULT_OK); |
+ CHECK(mapping); |
+ CHECK(mapping->base()); |
+ CHECK_EQ(mapping->length(), 100u); |
+ |
+ // Write some stuff to the shared buffer. |
+ static const char kHello[] = "hello"; |
+ memcpy(mapping->base(), kHello, sizeof(kHello)); |
+ |
+ // We should be able to close the dispatcher now. |
+ dispatcher->Close(); |
+ |
+ // And send a message to signal that we've written stuff. |
+ const std::string go2("go 2"); |
+ CHECK_EQ(mp->WriteMessage(0, |
+ &go2[0], |
+ static_cast<uint32_t>(go2.size()), |
+ NULL, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE), |
+ MOJO_RESULT_OK); |
+ |
+ // Now wait for our parent to send us a message. |
+ CHECK_EQ(WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE), MOJO_RESULT_OK); |
+ |
+ read_buffer = std::string(100, '\0'); |
+ num_bytes = static_cast<uint32_t>(read_buffer.size()); |
+ CHECK_EQ(mp->ReadMessage(0, |
+ &read_buffer[0], &num_bytes, |
+ NULL, NULL, |
+ MOJO_READ_MESSAGE_FLAG_NONE), |
+ MOJO_RESULT_OK); |
+ read_buffer.resize(num_bytes); |
+ CHECK_EQ(read_buffer, std::string("go 3")); |
+ |
+ // It should have written something to the shared buffer. |
+ static const char kWorld[] = "world!!!"; |
+ CHECK_EQ(memcmp(mapping->base(), kWorld, sizeof(kWorld)), 0); |
+ |
+ // And we're done. |
+ mp->Close(0); |
+ |
+ return 0; |
+} |
+ |
+#if defined(OS_POSIX) |
+#define MAYBE_SharedBufferPassing SharedBufferPassing |
+#else |
+// Not yet implemented (on Windows). |
+#define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing |
+#endif |
+TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { |
+ helper()->StartChild("CheckSharedBuffer"); |
+ |
+ scoped_refptr<MessagePipe> mp(new MessagePipe( |
+ scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
+ scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
+ Init(mp); |
+ |
+ // Make a shared buffer. |
+ scoped_refptr<SharedBufferDispatcher> dispatcher; |
+ MojoCreateSharedBufferOptions validated_options = {}; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ SharedBufferDispatcher::ValidateOptions(NULL, &validated_options)); |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ SharedBufferDispatcher::Create(validated_options, 100, |
+ &dispatcher)); |
+ ASSERT_TRUE(dispatcher); |
+ |
+ // Make a mapping. |
+ scoped_ptr<RawSharedBufferMapping> mapping; |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); |
+ ASSERT_TRUE(mapping); |
+ ASSERT_TRUE(mapping->base()); |
+ ASSERT_EQ(100u, mapping->length()); |
+ |
+ // Send the shared buffer. |
+ const std::string go1("go 1"); |
+ DispatcherTransport transport( |
+ test::DispatcherTryStartTransport(dispatcher.get())); |
+ ASSERT_TRUE(transport.is_valid()); |
+ |
+ std::vector<DispatcherTransport> transports; |
+ transports.push_back(transport); |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ mp->WriteMessage(0, |
+ &go1[0], |
+ static_cast<uint32_t>(go1.size()), |
+ &transports, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE)); |
+ transport.End(); |
+ |
+ EXPECT_TRUE(dispatcher->HasOneRef()); |
+ dispatcher = NULL; |
+ |
+ // Wait for a message from the child. |
+ EXPECT_EQ(MOJO_RESULT_OK, WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); |
+ |
+ std::string read_buffer(100, '\0'); |
+ uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ mp->ReadMessage(0, |
+ &read_buffer[0], &num_bytes, |
+ NULL, NULL, |
+ MOJO_READ_MESSAGE_FLAG_NONE)); |
+ read_buffer.resize(num_bytes); |
+ EXPECT_EQ(std::string("go 2"), read_buffer); |
+ |
+ // After we get it, the child should have written something to the shared |
+ // buffer. |
+ static const char kHello[] = "hello"; |
+ EXPECT_EQ(0, memcmp(mapping->base(), kHello, sizeof(kHello))); |
+ |
+ // Now we'll write some stuff to the shared buffer. |
+ static const char kWorld[] = "world!!!"; |
+ memcpy(mapping->base(), kWorld, sizeof(kWorld)); |
+ |
+ // And send a message to signal that we've written stuff. |
+ const std::string go3("go 3"); |
+ EXPECT_EQ(MOJO_RESULT_OK, |
+ mp->WriteMessage(0, |
+ &go3[0], |
+ static_cast<uint32_t>(go3.size()), |
+ NULL, |
+ MOJO_WRITE_MESSAGE_FLAG_NONE)); |
+ |
+ // Wait for |mp| to become readable, which should fail. |
+ EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
+ WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); |
+ |
+ mp->Close(0); |
+ |
+ EXPECT_EQ(0, helper()->WaitForChildShutdown()); |
+} |
+ |
MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { |
ChannelThread channel_thread; |
embedder::ScopedPlatformHandle client_platform_handle = |