Index: ipc/ipc_channel_unittest.cc |
diff --git a/ipc/ipc_channel_unittest.cc b/ipc/ipc_channel_unittest.cc |
index aa5da1526ad916c01634f4775e7e05be00cbf2da..db9dd3c47ab8fdf1d3c554264210e41d35a95917 100644 |
--- a/ipc/ipc_channel_unittest.cc |
+++ b/ipc/ipc_channel_unittest.cc |
@@ -6,66 +6,20 @@ |
#if defined(OS_WIN) |
#include <windows.h> |
-#elif defined(OS_POSIX) |
-#include <sys/types.h> |
-#include <unistd.h> |
#endif |
-#include <stdio.h> |
#include <string> |
-#include <utility> |
-#include "base/command_line.h" |
+#include "base/message_loop.h" |
#include "base/pickle.h" |
#include "base/threading/thread.h" |
-#include "base/time.h" |
-#include "ipc/ipc_descriptors.h" |
-#include "ipc/ipc_channel.h" |
-#include "ipc/ipc_channel_proxy.h" |
-#include "ipc/ipc_message_utils.h" |
-#include "ipc/ipc_multiprocess_test.h" |
-#include "ipc/ipc_sender.h" |
-#include "ipc/ipc_switches.h" |
+#include "ipc/ipc_message.h" |
#include "ipc/ipc_test_base.h" |
namespace { |
const size_t kLongMessageStringNumBytes = 50000; |
-class IPCChannelTest : public IPCTestBase { |
-}; |
- |
-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)); |
-} |
- |
static void Send(IPC::Sender* sender, const char* text) { |
static int message_index = 0; |
@@ -85,9 +39,15 @@ static void Send(IPC::Sender* sender, const char* text) { |
sender->Send(message); |
} |
-class MyChannelListener : public IPC::Listener { |
+// A generic listener that expects messages of a certain type (see |
+// OnMessageReceived()), and either sends a generic response or quits after the |
+// 50th message (or on channel error). |
+class GenericChannelListener : public IPC::Listener { |
public: |
- virtual bool OnMessageReceived(const IPC::Message& message) { |
+ GenericChannelListener() : sender_(NULL), messages_left_(50) {} |
+ virtual ~GenericChannelListener() {} |
+ |
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
PickleIterator iter(message); |
int ignored; |
@@ -98,16 +58,11 @@ class MyChannelListener : public IPC::Listener { |
EXPECT_TRUE(iter.ReadString(&big_string)); |
EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length()); |
- |
- if (--messages_left_ == 0) { |
- MessageLoop::current()->Quit(); |
- } else { |
- Send(sender_, "Foo"); |
- } |
+ SendNextMessage(); |
return true; |
} |
- virtual void OnChannelError() { |
+ virtual void OnChannelError() OVERRIDE { |
// There is a race when closing the channel so the last message may be lost. |
EXPECT_LE(messages_left_, 1); |
MessageLoop::current()->Quit(); |
@@ -115,7 +70,14 @@ class MyChannelListener : public IPC::Listener { |
void Init(IPC::Sender* s) { |
sender_ = s; |
- messages_left_ = 50; |
+ } |
+ |
+ protected: |
+ void SendNextMessage() { |
+ if (--messages_left_ <= 0) |
+ MessageLoop::current()->Quit(); |
+ else |
+ Send(sender_, "Foo"); |
} |
private: |
@@ -123,163 +85,138 @@ class MyChannelListener : public IPC::Listener { |
int messages_left_; |
}; |
-TEST_F(IPCChannelTest, ChannelTest) { |
- MyChannelListener channel_listener; |
- // Setup IPC channel. |
- IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER, |
- &channel_listener); |
- ASSERT_TRUE(chan.Connect()); |
+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)); |
+} |
- channel_listener.Init(&chan); |
+TEST_F(IPCChannelTest, ChannelTest) { |
+ Init("GenericClient"); |
- base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan); |
- ASSERT_TRUE(process_handle); |
+ // Set up IPC channel and start client. |
+ GenericChannelListener listener; |
+ CreateChannel(&listener); |
+ listener.Init(sender()); |
+ ASSERT_TRUE(ConnectChannel()); |
+ ASSERT_TRUE(StartClient()); |
- Send(&chan, "hello from parent"); |
+ Send(sender(), "hello from parent"); |
// Run message loop. |
MessageLoop::current()->Run(); |
- // Close Channel so client gets its OnChannelError() callback fired. |
- chan.Close(); |
+ // Close the channel so the client's OnChannelError() gets fired. |
+ channel()->Close(); |
- // Cleanup child process. |
- EXPECT_TRUE(base::WaitForSingleProcess( |
- process_handle, base::TimeDelta::FromSeconds(5))); |
- base::CloseProcessHandle(process_handle); |
+ EXPECT_TRUE(WaitForClientShutdown()); |
+ DestroyChannel(); |
} |
+// TODO(viettrungluu): Move to a separate IPCChannelWinTest. |
#if defined(OS_WIN) |
TEST_F(IPCChannelTest, ChannelTestExistingPipe) { |
- MyChannelListener channel_listener; |
- // Setup IPC channel with existing pipe. Specify name in Chrome format. |
+ Init("GenericClient"); |
+ |
+ // Create pipe manually using the standard Chromium name and set up IPC |
+ // channel. |
+ GenericChannelListener listener; |
std::string name("\\\\.\\pipe\\chrome."); |
- name.append(kTestClientChannel); |
- const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | |
- FILE_FLAG_FIRST_PIPE_INSTANCE; |
+ name.append(GetChannelName("GenericClient")); |
HANDLE pipe = CreateNamedPipeA(name.c_str(), |
- open_mode, |
+ PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | |
+ FILE_FLAG_FIRST_PIPE_INSTANCE, |
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, |
1, |
4096, |
4096, |
5000, |
NULL); |
- IPC::Channel chan(IPC::ChannelHandle(pipe), IPC::Channel::MODE_SERVER, |
- &channel_listener); |
- // Channel will duplicate the handle. |
- CloseHandle(pipe); |
- ASSERT_TRUE(chan.Connect()); |
+ CreateChannelFromChannelHandle(IPC::ChannelHandle(pipe), &listener); |
+ CloseHandle(pipe); // The channel duplicates the handle. |
+ listener.Init(sender()); |
- channel_listener.Init(&chan); |
+ // Connect to channel and start client. |
+ ASSERT_TRUE(ConnectChannel()); |
+ ASSERT_TRUE(StartClient()); |
- base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &chan); |
- ASSERT_TRUE(process_handle); |
- |
- Send(&chan, "hello from parent"); |
+ Send(sender(), "hello from parent"); |
// Run message loop. |
MessageLoop::current()->Run(); |
- // Close Channel so client gets its OnChannelError() callback fired. |
- chan.Close(); |
+ // Close the channel so the client's OnChannelError() gets fired. |
+ channel()->Close(); |
- // Cleanup child process. |
- EXPECT_TRUE(base::WaitForSingleProcess( |
- process_handle, base::TimeDelta::FromSeconds(5))); |
- base::CloseProcessHandle(process_handle); |
+ EXPECT_TRUE(WaitForClientShutdown()); |
+ DestroyChannel(); |
} |
#endif // defined (OS_WIN) |
TEST_F(IPCChannelTest, ChannelProxyTest) { |
- MyChannelListener channel_listener; |
+ Init("GenericClient"); |
- // The thread needs to out-live the ChannelProxy. |
base::Thread thread("ChannelProxyTestServer"); |
base::Thread::Options options; |
options.message_loop_type = MessageLoop::TYPE_IO; |
thread.StartWithOptions(options); |
- { |
- // setup IPC channel proxy |
- IPC::ChannelProxy chan(kTestClientChannel, IPC::Channel::MODE_SERVER, |
- &channel_listener, thread.message_loop_proxy()); |
- channel_listener.Init(&chan); |
+ // Set up IPC channel proxy. |
+ GenericChannelListener listener; |
+ CreateChannelProxy(&listener, thread.message_loop_proxy()); |
+ listener.Init(sender()); |
-#if defined(OS_WIN) |
- base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, NULL); |
-#elif defined(OS_POSIX) |
- bool debug_on_start = CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kDebugChildren); |
- base::FileHandleMappingVector fds_to_map; |
- const int ipcfd = chan.GetClientFileDescriptor(); |
- if (ipcfd > -1) { |
- fds_to_map.push_back(std::pair<int, int>(ipcfd, kPrimaryIPCChannel + 3)); |
- } |
- |
- base::ProcessHandle process_handle = MultiProcessTest::SpawnChild( |
- "RunTestClient", |
- fds_to_map, |
- debug_on_start); |
-#endif // defined(OS_POSIX) |
- |
- ASSERT_TRUE(process_handle); |
- |
- Send(&chan, "hello from parent"); |
- |
- // run message loop |
- MessageLoop::current()->Run(); |
- |
- // cleanup child process |
- EXPECT_TRUE(base::WaitForSingleProcess( |
- process_handle, base::TimeDelta::FromSeconds(5))); |
- base::CloseProcessHandle(process_handle); |
- } |
- thread.Stop(); |
-} |
+ ASSERT_TRUE(StartClient()); |
-class ChannelListenerWithOnConnectedSend : public IPC::Listener { |
- public: |
- virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { |
- SendNextMessage(); |
- } |
+ Send(sender(), "hello from parent"); |
- virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
- PickleIterator iter(message); |
+ // Run message loop. |
+ MessageLoop::current()->Run(); |
- int ignored; |
- EXPECT_TRUE(iter.ReadInt(&ignored)); |
- std::string data; |
- EXPECT_TRUE(iter.ReadString(&data)); |
- std::string big_string; |
- EXPECT_TRUE(iter.ReadString(&big_string)); |
- EXPECT_EQ(kLongMessageStringNumBytes - 1, big_string.length()); |
- SendNextMessage(); |
- return true; |
- } |
+ EXPECT_TRUE(WaitForClientShutdown()); |
- virtual void OnChannelError() OVERRIDE { |
- // There is a race when closing the channel so the last message may be lost. |
- EXPECT_LE(messages_left_, 1); |
- MessageLoop::current()->Quit(); |
- } |
+ // Destroy the channel proxy before shutting down the thread. |
+ DestroyChannelProxy(); |
+ thread.Stop(); |
+} |
- void Init(IPC::Sender* s) { |
- sender_ = s; |
- messages_left_ = 50; |
- } |
+class ChannelListenerWithOnConnectedSend : public GenericChannelListener { |
+ public: |
+ ChannelListenerWithOnConnectedSend() {} |
+ virtual ~ChannelListenerWithOnConnectedSend() {} |
- private: |
- void SendNextMessage() { |
- if (--messages_left_ == 0) { |
- MessageLoop::current()->Quit(); |
- } else { |
- Send(sender_, "Foo"); |
- } |
+ virtual void OnChannelConnected(int32 peer_pid) OVERRIDE { |
+ SendNextMessage(); |
} |
- |
- IPC::Sender* sender_; |
- int messages_left_; |
}; |
#if defined(OS_WIN) |
@@ -288,45 +225,42 @@ class ChannelListenerWithOnConnectedSend : public IPC::Listener { |
#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) { |
- // This tests the case of a listener sending back an event in it's |
- // OnChannelConnected handler. |
- |
- ChannelListenerWithOnConnectedSend channel_listener; |
- // Setup IPC channel. |
- IPC::Channel channel(kTestClientChannel, IPC::Channel::MODE_SERVER, |
- &channel_listener); |
- channel_listener.Init(&channel); |
- ASSERT_TRUE(channel.Connect()); |
+ Init("GenericClient"); |
- base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &channel); |
- ASSERT_TRUE(process_handle); |
+ // Set up IPC channel and start client. |
+ ChannelListenerWithOnConnectedSend listener; |
+ CreateChannel(&listener); |
+ listener.Init(sender()); |
+ ASSERT_TRUE(ConnectChannel()); |
+ ASSERT_TRUE(StartClient()); |
- Send(&channel, "hello from parent"); |
+ Send(sender(), "hello from parent"); |
// Run message loop. |
MessageLoop::current()->Run(); |
- // Close Channel so client gets its OnChannelError() callback fired. |
- channel.Close(); |
+ // Close the channel so the client's OnChannelError() gets fired. |
+ channel()->Close(); |
- // Cleanup child process. |
- EXPECT_TRUE(base::WaitForSingleProcess( |
- process_handle, base::TimeDelta::FromSeconds(5))); |
- base::CloseProcessHandle(process_handle); |
+ EXPECT_TRUE(WaitForClientShutdown()); |
+ DestroyChannel(); |
} |
-MULTIPROCESS_IPC_TEST_MAIN(RunTestClient) { |
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(GenericClient) { |
MessageLoopForIO main_message_loop; |
- MyChannelListener channel_listener; |
- |
- // setup IPC channel |
- IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT, |
- &channel_listener); |
- CHECK(chan.Connect()); |
- channel_listener.Init(&chan); |
- Send(&chan, "hello from child"); |
- // run message loop |
+ GenericChannelListener listener; |
+ |
+ // Set up IPC channel. |
+ IPC::Channel channel(IPCTestBase::GetChannelName("GenericClient"), |
+ IPC::Channel::MODE_CLIENT, |
+ &listener); |
+ CHECK(channel.Connect()); |
+ listener.Init(&channel); |
+ Send(&channel, "hello from child"); |
+ |
MessageLoop::current()->Run(); |
return 0; |
} |