| // Copyright (c) 2012 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 "build/build_config.h" |
| |
| #if defined(OS_WIN) |
| #include <windows.h> |
| #endif |
| |
| #include <string> |
| |
| #include "base/message_loop/message_loop.h" |
| #include "base/pickle.h" |
| #include "base/threading/thread.h" |
| #include "ipc/ipc_message.h" |
| #include "ipc/ipc_test_base.h" |
| #include "ipc/ipc_test_channel_listener.h" |
| |
| namespace { |
| |
| class IPCChannelTest : public IPCTestBase { |
| }; |
| |
| // TODO(viettrungluu): Move to a separate IPCMessageTest. |
| TEST_F(IPCChannelTest, BasicMessageTest) { |
| int v1 = 10; |
| std::string v2("foobar"); |
| std::wstring v3(L"hello world"); |
| |
| IPC::Message m(0, 1, IPC::Message::PRIORITY_NORMAL); |
| EXPECT_TRUE(m.WriteInt(v1)); |
| EXPECT_TRUE(m.WriteString(v2)); |
| EXPECT_TRUE(m.WriteWString(v3)); |
| |
| PickleIterator iter(m); |
| |
| int vi; |
| std::string vs; |
| std::wstring vw; |
| |
| EXPECT_TRUE(m.ReadInt(&iter, &vi)); |
| EXPECT_EQ(v1, vi); |
| |
| EXPECT_TRUE(m.ReadString(&iter, &vs)); |
| EXPECT_EQ(v2, vs); |
| |
| EXPECT_TRUE(m.ReadWString(&iter, &vw)); |
| EXPECT_EQ(v3, vw); |
| |
| // should fail |
| EXPECT_FALSE(m.ReadInt(&iter, &vi)); |
| EXPECT_FALSE(m.ReadString(&iter, &vs)); |
| EXPECT_FALSE(m.ReadWString(&iter, &vw)); |
| } |
| |
| TEST_F(IPCChannelTest, ChannelTest) { |
| Init("GenericClient"); |
| |
| // Set up IPC channel and start client. |
| IPC::TestChannelListener listener; |
| CreateChannel(&listener); |
| listener.Init(sender()); |
| ASSERT_TRUE(ConnectChannel()); |
| ASSERT_TRUE(StartClient()); |
| |
| IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); |
| |
| // Run message loop. |
| base::MessageLoop::current()->Run(); |
| |
| // Close the channel so the client's OnChannelError() gets fired. |
| channel()->Close(); |
| |
| EXPECT_TRUE(WaitForClientShutdown()); |
| DestroyChannel(); |
| } |
| |
| // TODO(viettrungluu): Move to a separate IPCChannelWinTest. |
| #if defined(OS_WIN) |
| TEST_F(IPCChannelTest, ChannelTestExistingPipe) { |
| Init("GenericClient"); |
| |
| // Create pipe manually using the standard Chromium name and set up IPC |
| // channel. |
| IPC::TestChannelListener listener; |
| std::string name("\\\\.\\pipe\\chrome."); |
| name.append(GetChannelName("GenericClient")); |
| HANDLE pipe = CreateNamedPipeA(name.c_str(), |
| PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | |
| FILE_FLAG_FIRST_PIPE_INSTANCE, |
| PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, |
| 1, |
| 4096, |
| 4096, |
| 5000, |
| NULL); |
| CreateChannelFromChannelHandle(IPC::ChannelHandle(pipe), &listener); |
| CloseHandle(pipe); // The channel duplicates the handle. |
| listener.Init(sender()); |
| |
| // Connect to channel and start client. |
| ASSERT_TRUE(ConnectChannel()); |
| ASSERT_TRUE(StartClient()); |
| |
| IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); |
| |
| // Run message loop. |
| base::MessageLoop::current()->Run(); |
| |
| // Close the channel so the client's OnChannelError() gets fired. |
| channel()->Close(); |
| |
| EXPECT_TRUE(WaitForClientShutdown()); |
| DestroyChannel(); |
| } |
| #endif // defined (OS_WIN) |
| |
| TEST_F(IPCChannelTest, ChannelProxyTest) { |
| Init("GenericClient"); |
| |
| base::Thread thread("ChannelProxyTestServer"); |
| base::Thread::Options options; |
| options.message_loop_type = base::MessageLoop::TYPE_IO; |
| thread.StartWithOptions(options); |
| |
| // Set up IPC channel proxy. |
| IPC::TestChannelListener listener; |
| CreateChannelProxy(&listener, thread.message_loop_proxy().get()); |
| listener.Init(sender()); |
| |
| ASSERT_TRUE(StartClient()); |
| |
| IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); |
| |
| // Run message loop. |
| base::MessageLoop::current()->Run(); |
| |
| EXPECT_TRUE(WaitForClientShutdown()); |
| |
| // Destroy the channel proxy before shutting down the thread. |
| DestroyChannelProxy(); |
| thread.Stop(); |
| } |
| |
| class ChannelListenerWithOnConnectedSend : public IPC::TestChannelListener { |
| public: |
| ChannelListenerWithOnConnectedSend() {} |
| virtual ~ChannelListenerWithOnConnectedSend() {} |
| |
| virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { |
| SendNextMessage(); |
| } |
| }; |
| |
| #if defined(OS_WIN) |
| // Acting flakey in Windows. http://crbug.com/129595 |
| #define MAYBE_SendMessageInChannelConnected DISABLED_SendMessageInChannelConnected |
| #else |
| #define MAYBE_SendMessageInChannelConnected SendMessageInChannelConnected |
| #endif |
| // This tests the case of a listener sending back an event in its |
| // OnChannelConnected handler. |
| TEST_F(IPCChannelTest, MAYBE_SendMessageInChannelConnected) { |
| Init("GenericClient"); |
| |
| // Set up IPC channel and start client. |
| ChannelListenerWithOnConnectedSend listener; |
| CreateChannel(&listener); |
| listener.Init(sender()); |
| ASSERT_TRUE(ConnectChannel()); |
| ASSERT_TRUE(StartClient()); |
| |
| IPC::TestChannelListener::SendOneMessage(sender(), "hello from parent"); |
| |
| // Run message loop. |
| base::MessageLoop::current()->Run(); |
| |
| // Close the channel so the client's OnChannelError() gets fired. |
| channel()->Close(); |
| |
| EXPECT_TRUE(WaitForClientShutdown()); |
| DestroyChannel(); |
| } |
| |
| MULTIPROCESS_IPC_TEST_CLIENT_MAIN(GenericClient) { |
| base::MessageLoopForIO main_message_loop; |
| IPC::TestChannelListener listener; |
| |
| // Set up IPC channel. |
| scoped_ptr<IPC::Channel> channel(IPC::Channel::CreateClient( |
| IPCTestBase::GetChannelName("GenericClient"), |
| &listener)); |
| CHECK(channel->Connect()); |
| listener.Init(channel.get()); |
| IPC::TestChannelListener::SendOneMessage(channel.get(), "hello from child"); |
| |
| base::MessageLoop::current()->Run(); |
| return 0; |
| } |
| |
| } // namespace |