Chromium Code Reviews| Index: mojo/edk/embedder/embedder_multiprocess_unittest.cc |
| diff --git a/mojo/edk/embedder/embedder_multiprocess_unittest.cc b/mojo/edk/embedder/embedder_multiprocess_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0900b53c6c5d33d382d9e76453d76a1be8c98df2 |
| --- /dev/null |
| +++ b/mojo/edk/embedder/embedder_multiprocess_unittest.cc |
| @@ -0,0 +1,234 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
|
viettrungluu
2014/11/21 22:18:41
Can't you just disable individual tests (using sui
qsr
2014/11/24 12:00:47
I can, and will as you seem to prefer it, but doin
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "mojo/edk/embedder/embedder.h" |
| + |
| +#include "mojo/edk/embedder/embedder_test_util.h" |
| +#include "mojo/edk/embedder/test_embedder.h" |
| +#include "mojo/edk/test/multiprocess_test_helper.h" |
| + |
| +namespace mojo { |
| +namespace embedder { |
| +namespace { |
| + |
| +// The sequence of messages sent is: |
| +// server_mp client_mp mp0 mp1 mp2 mp3 |
| +// 1. "hello" |
| +// 2. "world!" |
| +// 3. "FOO" |
| +// 4. "Bar"+mp1 |
| +// 5. (close) |
| +// 6. (close) |
| +// 7. "baz" |
| +// 8. (closed) |
| +// 9. "quux"+mp2 |
| +// 10. (close) |
| +// 11. (wait/cl.) |
| +// 12. (wait/cl.) |
| +TEST_F(EmbedderTest, MultiprocessChannels) { |
| + mojo::embedder::test::InitWithSimplePlatformSupport(); |
| + mojo::test::MultiprocessTestHelper multiprocess_test_helper; |
| + multiprocess_test_helper.StartChild("MultiprocessChannelsClient"); |
| + |
| + { |
| + ScopedTestChannel server_channel( |
| + test_io_thread()->task_runner(), |
| + multiprocess_test_helper.server_platform_handle.Pass()); |
| + MojoHandle server_mp = server_channel.bootstrap_message_pipe(); |
| + EXPECT_NE(server_mp, MOJO_HANDLE_INVALID); |
| + server_channel.WaitForChannelCreationCompletion(); |
| + EXPECT_TRUE(server_channel.channel_info()); |
| + |
| + // 1. Write a message to |server_mp| (attaching nothing). |
| + const char kHello[] = "hello"; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoWriteMessage(server_mp, kHello, |
| + static_cast<uint32_t>(sizeof(kHello)), nullptr, |
| + 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| + |
| + // TODO(vtl): If the scope were ended immediately here (maybe after closing |
| + // |server_mp|), we die with a fatal error in |Channel::HandleLocalError()|. |
| + |
| + // 2. Read a message from |server_mp|. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoWait(server_mp, MOJO_HANDLE_SIGNAL_READABLE, |
| + MOJO_DEADLINE_INDEFINITE)); |
| + char buffer[1000] = {}; |
| + uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoReadMessage(server_mp, buffer, &num_bytes, nullptr, nullptr, |
| + MOJO_READ_MESSAGE_FLAG_NONE)); |
| + const char kWorld[] = "world!"; |
| + EXPECT_EQ(sizeof(kWorld), num_bytes); |
| + EXPECT_STREQ(kWorld, buffer); |
| + |
| + // Create a new message pipe (endpoints |mp0| and |mp1|). |
| + MojoHandle mp0, mp1; |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp0, &mp1)); |
| + |
| + // 3. Write something to |mp0|. |
| + const char kFoo[] = "FOO"; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoWriteMessage(mp0, kFoo, static_cast<uint32_t>(sizeof(kFoo)), |
| + nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| + |
| + // 4. Write a message to |server_mp|, attaching |mp1|. |
| + const char kBar[] = "Bar"; |
| + EXPECT_EQ( |
| + MOJO_RESULT_OK, |
| + MojoWriteMessage(server_mp, kBar, static_cast<uint32_t>(sizeof(kBar)), |
| + &mp1, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| + mp1 = MOJO_HANDLE_INVALID; |
| + |
| + // 5. Close |server_mp|. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(server_mp)); |
| + |
| + // 9. Read a message from |mp0|, which should have |mp2| attached. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp0, MOJO_HANDLE_SIGNAL_READABLE, |
| + MOJO_DEADLINE_INDEFINITE)); |
| + memset(buffer, 0, sizeof(buffer)); |
| + num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
| + MojoHandle mp2 = MOJO_HANDLE_INVALID; |
| + uint32_t num_handles = 1; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoReadMessage(mp0, buffer, &num_bytes, &mp2, &num_handles, |
| + MOJO_READ_MESSAGE_FLAG_NONE)); |
| + const char kQuux[] = "quux"; |
| + EXPECT_EQ(sizeof(kQuux), num_bytes); |
| + EXPECT_STREQ(kQuux, buffer); |
| + EXPECT_EQ(1u, num_handles); |
| + EXPECT_NE(mp2, MOJO_HANDLE_INVALID); |
| + |
| + // 7. Read a message from |mp2|. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, |
| + MOJO_DEADLINE_INDEFINITE)); |
| + memset(buffer, 0, sizeof(buffer)); |
| + num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoReadMessage(mp2, buffer, &num_bytes, nullptr, nullptr, |
| + MOJO_READ_MESSAGE_FLAG_NONE)); |
| + const char kBaz[] = "baz"; |
| + EXPECT_EQ(sizeof(kBaz), num_bytes); |
| + EXPECT_STREQ(kBaz, buffer); |
| + |
| + // 10. Close |mp0|. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp0)); |
| + |
| +// 12. Wait on |mp2| (which should eventually fail) and then close it. |
| +// TODO(vtl): crbug.com/351768 |
| +#if 0 |
| + EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| + MojoWait(mp2, MOJO_HANDLE_SIGNAL_READABLE, |
| + MOJO_DEADLINE_INDEFINITE)); |
| +#endif |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp2)); |
| + } |
| + |
| + EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown()); |
| + EXPECT_TRUE(test::Shutdown()); |
| +} |
| + |
| +MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessChannelsClient) { |
| + ScopedPlatformHandle client_platform_handle = |
| + mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); |
| + EXPECT_TRUE(client_platform_handle.is_valid()); |
| + |
| + base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart); |
| + mojo::embedder::test::InitWithSimplePlatformSupport(); |
| + |
| + { |
| + ScopedTestChannel client_channel(test_io_thread.task_runner(), |
| + client_platform_handle.Pass()); |
| + MojoHandle client_mp = client_channel.bootstrap_message_pipe(); |
| + EXPECT_NE(client_mp, MOJO_HANDLE_INVALID); |
| + client_channel.WaitForChannelCreationCompletion(); |
| + CHECK(client_channel.channel_info() != nullptr); |
| + |
| + // 1. Read the first message from |client_mp|. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, |
| + MOJO_DEADLINE_INDEFINITE)); |
| + char buffer[1000] = {}; |
| + uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoReadMessage(client_mp, buffer, &num_bytes, nullptr, nullptr, |
| + MOJO_READ_MESSAGE_FLAG_NONE)); |
| + const char kHello[] = "hello"; |
| + EXPECT_EQ(sizeof(kHello), num_bytes); |
| + EXPECT_STREQ(kHello, buffer); |
| + |
| + // 2. Write a message to |client_mp| (attaching nothing). |
| + const char kWorld[] = "world!"; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoWriteMessage(client_mp, kWorld, |
| + static_cast<uint32_t>(sizeof(kWorld)), nullptr, |
| + 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| + |
| + // 4. Read a message from |client_mp|, which should have |mp1| attached. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoWait(client_mp, MOJO_HANDLE_SIGNAL_READABLE, |
| + MOJO_DEADLINE_INDEFINITE)); |
| + // TODO(vtl): If the scope were to end here (and |client_mp| closed), we'd |
| + // die (again due to |Channel::HandleLocalError()|). |
| + memset(buffer, 0, sizeof(buffer)); |
| + num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
| + MojoHandle mp1 = MOJO_HANDLE_INVALID; |
| + uint32_t num_handles = 1; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoReadMessage(client_mp, buffer, &num_bytes, &mp1, &num_handles, |
| + MOJO_READ_MESSAGE_FLAG_NONE)); |
| + const char kBar[] = "Bar"; |
| + EXPECT_EQ(sizeof(kBar), num_bytes); |
| + EXPECT_STREQ(kBar, buffer); |
| + EXPECT_EQ(1u, num_handles); |
| + EXPECT_NE(mp1, MOJO_HANDLE_INVALID); |
| + // TODO(vtl): If the scope were to end here (and the two handles closed), |
| + // we'd die due to |Channel::RunRemoteMessagePipeEndpoint()| not handling |
| + // write errors (assuming the parent had closed the pipe). |
| + |
| + // 6. Close |client_mp|. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(client_mp)); |
| + |
| + // Create a new message pipe (endpoints |mp2| and |mp3|). |
| + MojoHandle mp2, mp3; |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &mp2, &mp3)); |
| + |
| + // 7. Write a message to |mp3|. |
| + const char kBaz[] = "baz"; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoWriteMessage(mp3, kBaz, static_cast<uint32_t>(sizeof(kBaz)), |
| + nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| + |
| + // 8. Close |mp3|. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp3)); |
| + |
| + // 9. Write a message to |mp1|, attaching |mp2|. |
| + const char kQuux[] = "quux"; |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoWriteMessage(mp1, kQuux, static_cast<uint32_t>(sizeof(kQuux)), |
| + &mp2, 1, MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| + mp2 = MOJO_HANDLE_INVALID; |
| + |
| + // 3. Read a message from |mp1|. |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, |
| + MOJO_DEADLINE_INDEFINITE)); |
| + memset(buffer, 0, sizeof(buffer)); |
| + num_bytes = static_cast<uint32_t>(sizeof(buffer)); |
| + EXPECT_EQ(MOJO_RESULT_OK, |
| + MojoReadMessage(mp1, buffer, &num_bytes, nullptr, nullptr, |
| + MOJO_READ_MESSAGE_FLAG_NONE)); |
| + const char kFoo[] = "FOO"; |
| + EXPECT_EQ(sizeof(kFoo), num_bytes); |
| + EXPECT_STREQ(kFoo, buffer); |
| + |
| + // 11. Wait on |mp1| (which should eventually fail) and then close it. |
| + EXPECT_EQ( |
| + MOJO_RESULT_FAILED_PRECONDITION, |
| + MojoWait(mp1, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE)); |
| + EXPECT_EQ(MOJO_RESULT_OK, MojoClose(mp1)); |
| + } |
| + |
| + EXPECT_TRUE(test::Shutdown()); |
| +} |
| + |
| +} // namespace |
| +} // namespace embedder |
| +} // namespace mojo |