Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Unified Diff: third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc

Issue 1179733005: Update mojo sdk to rev bdbb0c7e396fc4044a8b194058d7a7e529715286 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update CommandBufferImpl (Binding::OnConnectionError is no more) Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc
diff --git a/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc b/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b613e457fec49698898054d9e93a0b128df6ce33
--- /dev/null
+++ b/third_party/mojo/src/mojo/edk/system/ipc_support_unittest.cc
@@ -0,0 +1,342 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/edk/system/ipc_support.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/test_io_thread.h"
+#include "base/test/test_timeouts.h"
+#include "mojo/edk/embedder/master_process_delegate.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/simple_platform_support.h"
+#include "mojo/edk/embedder/slave_process_delegate.h"
+#include "mojo/edk/system/channel_manager.h"
+#include "mojo/edk/system/connection_identifier.h"
+#include "mojo/edk/system/message_pipe_dispatcher.h"
+#include "mojo/edk/system/process_identifier.h"
+#include "mojo/edk/system/test_utils.h"
+#include "mojo/edk/system/waiter.h"
+#include "mojo/edk/test/multiprocess_test_helper.h"
+#include "mojo/edk/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace system {
+namespace {
+
+const char kConnectionIdFlag[] = "test-connection-id";
+
+class TestMasterProcessDelegate : public embedder::MasterProcessDelegate {
+ public:
+ TestMasterProcessDelegate()
+ : on_slave_disconnect_event_(true, false) {} // Manual reset.
+ ~TestMasterProcessDelegate() override {}
+
+ bool TryWaitForOnSlaveDisconnect() {
+ return on_slave_disconnect_event_.TimedWait(TestTimeouts::action_timeout());
+ }
+
+ private:
+ // |embedder::MasterProcessDelegate| methods:
+ void OnShutdownComplete() override { NOTREACHED(); }
+
+ void OnSlaveDisconnect(embedder::SlaveInfo /*slave_info*/) override {
+ on_slave_disconnect_event_.Signal();
+ }
+
+ base::WaitableEvent on_slave_disconnect_event_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestMasterProcessDelegate);
+};
+
+class TestSlaveProcessDelegate : public embedder::SlaveProcessDelegate {
+ public:
+ TestSlaveProcessDelegate() {}
+ ~TestSlaveProcessDelegate() override {}
+
+ private:
+ // |embedder::SlaveProcessDelegate| methods:
+ void OnShutdownComplete() override { NOTREACHED(); }
+
+ void OnMasterDisconnect() override { NOTREACHED(); }
+
+ DISALLOW_COPY_AND_ASSIGN(TestSlaveProcessDelegate);
+};
+
+TEST(IPCSupportTest, MasterSlave) {
+ embedder::SimplePlatformSupport platform_support;
+ base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
+ TestMasterProcessDelegate master_process_delegate;
+ // Note: Run master process delegate methods on the I/O thread.
+ IPCSupport master_ipc_support(
+ &platform_support, embedder::ProcessType::MASTER,
+ test_io_thread.task_runner(), &master_process_delegate,
+ test_io_thread.task_runner(), embedder::ScopedPlatformHandle());
+
+ ConnectionIdentifier connection_id =
+ master_ipc_support.GenerateConnectionIdentifier();
+
+ embedder::PlatformChannelPair channel_pair;
+ // Note: |ChannelId|s and |ProcessIdentifier|s are interchangeable.
+ ProcessIdentifier slave_id = kInvalidProcessIdentifier;
+ base::WaitableEvent event1(true, false);
+ scoped_refptr<MessagePipeDispatcher> master_mp =
+ master_ipc_support.ConnectToSlave(
+ connection_id, nullptr, channel_pair.PassServerHandle(),
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event1)),
+ nullptr, &slave_id);
+ ASSERT_TRUE(master_mp);
+ EXPECT_NE(slave_id, kInvalidProcessIdentifier);
+ EXPECT_NE(slave_id, kMasterProcessIdentifier);
+ // Note: We don't have to wait on |event1| now, but we'll have to do so before
+ // tearing down the channel.
+
+ TestSlaveProcessDelegate slave_process_delegate;
+ // Note: Run process delegate methods on the I/O thread.
+ IPCSupport slave_ipc_support(
+ &platform_support, embedder::ProcessType::SLAVE,
+ test_io_thread.task_runner(), &slave_process_delegate,
+ test_io_thread.task_runner(), channel_pair.PassClientHandle());
+
+ ProcessIdentifier master_id = kInvalidProcessIdentifier;
+ base::WaitableEvent event2(true, false);
+ scoped_refptr<MessagePipeDispatcher> slave_mp =
+ slave_ipc_support.ConnectToMaster(
+ connection_id,
+ base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event2)),
+ nullptr, &master_id);
+ ASSERT_TRUE(slave_mp);
+ EXPECT_EQ(kMasterProcessIdentifier, master_id);
+
+ // Set up waiting on the slave end first (to avoid racing).
+ Waiter waiter;
+ waiter.Init();
+ ASSERT_EQ(
+ MOJO_RESULT_OK,
+ slave_mp->AddAwakable(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 0, nullptr));
+
+ // Write a message with just 'x' through the master's end.
+ EXPECT_EQ(MOJO_RESULT_OK,
+ master_mp->WriteMessage(UserPointer<const void>("x"), 1, nullptr,
+ MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+ // Wait for it to arrive.
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(test::ActionDeadline(), nullptr));
+ slave_mp->RemoveAwakable(&waiter, nullptr);
+
+ // Read the message from the slave's end.
+ char buffer[10] = {};
+ uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
+ EXPECT_EQ(MOJO_RESULT_OK,
+ slave_mp->ReadMessage(UserPointer<void>(buffer),
+ MakeUserPointer(&buffer_size), 0, nullptr,
+ MOJO_READ_MESSAGE_FLAG_NONE));
+ EXPECT_EQ(1u, buffer_size);
+ EXPECT_EQ('x', buffer[0]);
+
+ // Don't need the message pipe anymore.
+ master_mp->Close();
+ slave_mp->Close();
+
+ // A message was sent through the message pipe, |Channel|s must have been
+ // established on both sides. The events have thus almost certainly been
+ // signalled, but we'll wait just to be sure.
+ EXPECT_TRUE(event1.TimedWait(TestTimeouts::action_timeout()));
+ EXPECT_TRUE(event2.TimedWait(TestTimeouts::action_timeout()));
+
+ test_io_thread.PostTaskAndWait(
+ FROM_HERE,
+ base::Bind(&ChannelManager::ShutdownChannelOnIOThread,
+ base::Unretained(slave_ipc_support.channel_manager()),
+ master_id));
+ test_io_thread.PostTaskAndWait(
+ FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
+ base::Unretained(&slave_ipc_support)));
+
+ EXPECT_TRUE(master_process_delegate.TryWaitForOnSlaveDisconnect());
+
+ test_io_thread.PostTaskAndWait(
+ FROM_HERE,
+ base::Bind(&ChannelManager::ShutdownChannelOnIOThread,
+ base::Unretained(master_ipc_support.channel_manager()),
+ slave_id));
+ test_io_thread.PostTaskAndWait(
+ FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
+ base::Unretained(&master_ipc_support)));
+}
+
+} // namespace
+
+// Note: This test isn't in an anonymous namespace, since it needs to be
+// friended by |IPCSupport|.
+TEST(IPCSupportTest, MasterSlaveInternal) {
+ embedder::SimplePlatformSupport platform_support;
+ base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
+ TestMasterProcessDelegate master_process_delegate;
+ // Note: Run master process delegate methods on the I/O thread.
+ IPCSupport master_ipc_support(
+ &platform_support, embedder::ProcessType::MASTER,
+ test_io_thread.task_runner(), &master_process_delegate,
+ test_io_thread.task_runner(), embedder::ScopedPlatformHandle());
+
+ ConnectionIdentifier connection_id =
+ master_ipc_support.GenerateConnectionIdentifier();
+
+ embedder::PlatformChannelPair channel_pair;
+ ProcessIdentifier slave_id = kInvalidProcessIdentifier;
+ embedder::ScopedPlatformHandle master_second_platform_handle =
+ master_ipc_support.ConnectToSlaveInternal(
+ connection_id, nullptr, channel_pair.PassServerHandle(), &slave_id);
+ ASSERT_TRUE(master_second_platform_handle.is_valid());
+ EXPECT_NE(slave_id, kInvalidProcessIdentifier);
+ EXPECT_NE(slave_id, kMasterProcessIdentifier);
+
+ TestSlaveProcessDelegate slave_process_delegate;
+ // Note: Run process delegate methods on the I/O thread.
+ IPCSupport slave_ipc_support(
+ &platform_support, embedder::ProcessType::SLAVE,
+ test_io_thread.task_runner(), &slave_process_delegate,
+ test_io_thread.task_runner(), channel_pair.PassClientHandle());
+
+ embedder::ScopedPlatformHandle slave_second_platform_handle =
+ slave_ipc_support.ConnectToMasterInternal(connection_id);
+ ASSERT_TRUE(slave_second_platform_handle.is_valid());
+
+ // Write an 'x' through the master's end.
+ size_t n = 0;
+ EXPECT_TRUE(mojo::test::BlockingWrite(master_second_platform_handle.get(),
+ "x", 1, &n));
+ EXPECT_EQ(1u, n);
+
+ // Read it from the slave's end.
+ char c = '\0';
+ n = 0;
+ EXPECT_TRUE(
+ mojo::test::BlockingRead(slave_second_platform_handle.get(), &c, 1, &n));
+ EXPECT_EQ(1u, n);
+ EXPECT_EQ('x', c);
+
+ test_io_thread.PostTaskAndWait(
+ FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
+ base::Unretained(&slave_ipc_support)));
+
+ EXPECT_TRUE(master_process_delegate.TryWaitForOnSlaveDisconnect());
+
+ test_io_thread.PostTaskAndWait(
+ FROM_HERE, base::Bind(&IPCSupport::ShutdownOnIOThread,
+ base::Unretained(&master_ipc_support)));
+}
+
+// This is a true multiprocess version of IPCSupportTest.MasterSlaveInternal.
+// Note: This test isn't in an anonymous namespace, since it needs to be
+// friended by |IPCSupport|.
+#if defined(OS_ANDROID)
+// Android multi-process tests are not executing the new process. This is flaky.
+// TODO(vtl): I'm guessing this is true of this test too?
+#define MAYBE_MultiprocessMasterSlaveInternal \
+ DISABLED_MultiprocessMasterSlaveInternal
+#else
+#define MAYBE_MultiprocessMasterSlaveInternal MultiprocessMasterSlaveInternal
+#endif // defined(OS_ANDROID)
+TEST(IPCSupportTest, MAYBE_MultiprocessMasterSlaveInternal) {
+ embedder::SimplePlatformSupport platform_support;
+ base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
+ TestMasterProcessDelegate master_process_delegate;
+ // Note: Run process delegate methods on the I/O thread.
+ IPCSupport ipc_support(&platform_support, embedder::ProcessType::MASTER,
+ test_io_thread.task_runner(), &master_process_delegate,
+ test_io_thread.task_runner(),
+ embedder::ScopedPlatformHandle());
+
+ ConnectionIdentifier connection_id =
+ ipc_support.GenerateConnectionIdentifier();
+ mojo::test::MultiprocessTestHelper multiprocess_test_helper;
+ ProcessIdentifier slave_id = kInvalidProcessIdentifier;
+ embedder::ScopedPlatformHandle second_platform_handle =
+ ipc_support.ConnectToSlaveInternal(
+ connection_id, nullptr,
+ multiprocess_test_helper.server_platform_handle.Pass(), &slave_id);
+ ASSERT_TRUE(second_platform_handle.is_valid());
+ EXPECT_NE(slave_id, kInvalidProcessIdentifier);
+ EXPECT_NE(slave_id, kMasterProcessIdentifier);
+
+ multiprocess_test_helper.StartChildWithExtraSwitch(
+ "MultiprocessMasterSlaveInternal", kConnectionIdFlag,
+ connection_id.ToString());
+
+ // We write a '?'. The slave should write a '!' in response.
+ size_t n = 0;
+ EXPECT_TRUE(
+ mojo::test::BlockingWrite(second_platform_handle.get(), "?", 1, &n));
+ EXPECT_EQ(1u, n);
+
+ char c = '\0';
+ n = 0;
+ EXPECT_TRUE(
+ mojo::test::BlockingRead(second_platform_handle.get(), &c, 1, &n));
+ EXPECT_EQ(1u, n);
+ EXPECT_EQ('!', c);
+
+ EXPECT_TRUE(master_process_delegate.TryWaitForOnSlaveDisconnect());
+ EXPECT_TRUE(multiprocess_test_helper.WaitForChildTestShutdown());
+
+ test_io_thread.PostTaskAndWait(FROM_HERE,
+ base::Bind(&IPCSupport::ShutdownOnIOThread,
+ base::Unretained(&ipc_support)));
+}
+
+MOJO_MULTIPROCESS_TEST_CHILD_TEST(MultiprocessMasterSlaveInternal) {
+ embedder::ScopedPlatformHandle client_platform_handle =
+ mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
+ ASSERT_TRUE(client_platform_handle.is_valid());
+
+ embedder::SimplePlatformSupport platform_support;
+ base::TestIOThread test_io_thread(base::TestIOThread::kAutoStart);
+ TestSlaveProcessDelegate slave_process_delegate;
+ // Note: Run process delegate methods on the I/O thread.
+ IPCSupport ipc_support(&platform_support, embedder::ProcessType::SLAVE,
+ test_io_thread.task_runner(), &slave_process_delegate,
+ test_io_thread.task_runner(),
+ client_platform_handle.Pass());
+
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ ASSERT_TRUE(command_line.HasSwitch(kConnectionIdFlag));
+ bool ok = false;
+ ConnectionIdentifier connection_id = ConnectionIdentifier::FromString(
+ command_line.GetSwitchValueASCII(kConnectionIdFlag), &ok);
+ ASSERT_TRUE(ok);
+
+ embedder::ScopedPlatformHandle second_platform_handle =
+ ipc_support.ConnectToMasterInternal(connection_id);
+ ASSERT_TRUE(second_platform_handle.is_valid());
+
+ // The master should write a '?'. We'll write a '!' in response.
+ char c = '\0';
+ size_t n = 0;
+ EXPECT_TRUE(
+ mojo::test::BlockingRead(second_platform_handle.get(), &c, 1, &n));
+ EXPECT_EQ(1u, n);
+ EXPECT_EQ('?', c);
+
+ n = 0;
+ EXPECT_TRUE(
+ mojo::test::BlockingWrite(second_platform_handle.get(), "!", 1, &n));
+ EXPECT_EQ(1u, n);
+
+ test_io_thread.PostTaskAndWait(FROM_HERE,
+ base::Bind(&IPCSupport::ShutdownOnIOThread,
+ base::Unretained(&ipc_support)));
+}
+
+// TODO(vtl): Also test the case of the master "dying" before the slave. (The
+// slave should get OnMasterDisconnect(), which we currently don't test.)
+
+} // namespace system
+} // namespace mojo
« no previous file with comments | « third_party/mojo/src/mojo/edk/system/ipc_support.cc ('k') | third_party/mojo/src/mojo/edk/system/master_connection_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698