| 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;
|
| }
|
|
|