Index: content/browser/browser_associated_interface_unittest.cc |
diff --git a/content/browser/browser_associated_interface_unittest.cc b/content/browser/browser_associated_interface_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0c73a71162c78285109b79540b28741afdb65c15 |
--- /dev/null |
+++ b/content/browser/browser_associated_interface_unittest.cc |
@@ -0,0 +1,170 @@ |
+// Copyright 2016 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 <memory> |
+#include <string> |
+ |
+#include "base/memory/ref_counted.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/pickle.h" |
+#include "base/run_loop.h" |
+#include "base/single_thread_task_runner.h" |
+#include "base/strings/stringprintf.h" |
+#include "base/threading/thread.h" |
+#include "content/public/browser/browser_associated_interface.h" |
+#include "content/public/browser/browser_message_filter.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/test/test_browser_thread_bundle.h" |
+#include "content/test/test_browser_associated_interfaces.mojom.h" |
+#include "ipc/ipc_channel_factory.h" |
+#include "ipc/ipc_channel_mojo.h" |
+#include "ipc/ipc_channel_proxy.h" |
+#include "ipc/ipc_listener.h" |
+#include "ipc/ipc_message.h" |
+#include "mojo/public/cpp/system/message_pipe.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace content { |
+ |
+const int kNumTestMessages = 100; |
+ |
+class BrowserAssociatedInterfaceTest : public testing::Test { |
+ public: |
+ static void AddFilterToChannel(BrowserMessageFilter* filter, |
+ IPC::ChannelProxy* channel) { |
+ filter->RegisterAssociatedInterfaces(channel); |
+ channel->AddFilter(filter->GetFilter()); |
+ } |
+}; |
+ |
+class ProxyRunner : public IPC::Listener { |
+ public: |
+ ProxyRunner(mojo::ScopedMessagePipeHandle pipe, |
+ bool for_server, |
+ scoped_refptr<base::SingleThreadTaskRunner> ipc_task_runner) { |
+ std::unique_ptr<IPC::ChannelFactory> factory; |
+ if (for_server) { |
+ factory = IPC::ChannelMojo::CreateServerFactory( |
+ std::move(pipe), ipc_task_runner); |
+ } else { |
+ factory = IPC::ChannelMojo::CreateClientFactory( |
+ std::move(pipe), ipc_task_runner); |
+ } |
+ channel_ = IPC::ChannelProxy::Create( |
+ std::move(factory), this, ipc_task_runner); |
+ } |
+ |
+ void ShutDown() { channel_.reset(); } |
+ |
+ IPC::ChannelProxy* channel() { return channel_.get(); } |
+ |
+ private: |
+ // IPC::Listener: |
+ bool OnMessageReceived(const IPC::Message& message) override { return false; } |
+ |
+ std::unique_ptr<IPC::ChannelProxy> channel_; |
+}; |
+ |
+class TestDriverMessageFilter |
+ : public BrowserMessageFilter, |
+ public BrowserAssociatedInterface< |
+ mojom::BrowserAssociatedInterfaceTestDriver>, |
+ public mojom::BrowserAssociatedInterfaceTestDriver { |
+ public: |
+ TestDriverMessageFilter() |
+ : BrowserMessageFilter(0), |
+ BrowserAssociatedInterface<mojom::BrowserAssociatedInterfaceTestDriver>( |
+ this, this) { |
+ } |
+ |
+ private: |
+ ~TestDriverMessageFilter() override {} |
+ |
+ // BrowserMessageFilter: |
+ bool OnMessageReceived(const IPC::Message& message) override { |
+ std::string actual_string; |
+ base::PickleIterator iter(message); |
+ EXPECT_TRUE(iter.ReadString(&actual_string)); |
+ EXPECT_EQ(next_expected_string_, actual_string); |
+ message_count_++; |
+ return true; |
+ } |
+ |
+ // mojom::BrowserAssociatedInterfaceTestDriver: |
+ void ExpectString(const std::string& expected) override { |
+ next_expected_string_ = expected; |
+ } |
+ |
+ void RequestQuit(const RequestQuitCallback& callback) override { |
+ EXPECT_EQ(kNumTestMessages, message_count_); |
+ callback.Run(); |
+ base::MessageLoop::current()->QuitWhenIdle(); |
+ } |
+ |
+ std::string next_expected_string_; |
+ int message_count_ = 0; |
+}; |
+ |
+class TestClientRunner { |
+ public: |
+ explicit TestClientRunner(mojo::ScopedMessagePipeHandle pipe) |
+ : client_thread_("Test client") { |
+ client_thread_.Start(); |
+ client_thread_.task_runner()->PostTask( |
+ FROM_HERE, base::Bind(&RunTestClient, base::Passed(&pipe))); |
+ } |
+ |
+ ~TestClientRunner() { |
+ client_thread_.Stop(); |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ private: |
+ static void RunTestClient(mojo::ScopedMessagePipeHandle pipe) { |
+ base::Thread io_thread("Client IO thread"); |
+ io_thread.StartWithOptions( |
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
+ ProxyRunner proxy(std::move(pipe), false, io_thread.task_runner()); |
+ |
+ mojom::BrowserAssociatedInterfaceTestDriverAssociatedPtr driver; |
+ proxy.channel()->GetRemoteAssociatedInterface(&driver); |
+ |
+ for (int i = 0; i < kNumTestMessages; ++i) { |
+ std::string next_message = base::StringPrintf("test %d", i); |
+ driver->ExpectString(next_message); |
+ |
+ std::unique_ptr<IPC::Message> message(new IPC::Message); |
+ message->WriteString(next_message); |
+ proxy.channel()->Send(message.release()); |
+ } |
+ |
+ driver->RequestQuit(base::MessageLoop::QuitWhenIdleClosure()); |
+ |
+ base::MessageLoop::ScopedNestableTaskAllower allow_nested_loops( |
+ base::MessageLoop::current()); |
+ base::RunLoop().Run(); |
+ |
+ proxy.ShutDown(); |
+ io_thread.Stop(); |
+ base::RunLoop().RunUntilIdle(); |
+ } |
+ |
+ base::Thread client_thread_; |
+}; |
+ |
+TEST_F(BrowserAssociatedInterfaceTest, Basic) { |
+ TestBrowserThreadBundle browser_threads_; |
+ mojo::MessagePipe pipe; |
+ ProxyRunner proxy(std::move(pipe.handle0), true, |
+ BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)); |
+ AddFilterToChannel(new TestDriverMessageFilter, proxy.channel()); |
+ |
+ TestClientRunner client(std::move(pipe.handle1)); |
+ base::RunLoop().Run(); |
+ |
+ proxy.ShutDown(); |
+ base::RunLoop().RunUntilIdle(); |
+} |
+ |
+} // namespace content |