| 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 =
|
|
|