summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipc/ipc.gyp5
-rw-r--r--ipc/ipc_channel_unittest.cc330
-rw-r--r--ipc/ipc_fuzzing_tests.cc102
-rw-r--r--ipc/ipc_multiprocess_test.cc4
-rw-r--r--ipc/ipc_multiprocess_test.h18
-rw-r--r--ipc/ipc_perftests.cc54
-rw-r--r--ipc/ipc_send_fds_test.cc166
-rw-r--r--ipc/ipc_test_base.cc174
-rw-r--r--ipc/ipc_test_base.h99
-rw-r--r--ipc/sync_socket_unittest.cc38
10 files changed, 472 insertions, 518 deletions
diff --git a/ipc/ipc.gyp b/ipc/ipc.gyp
index edc53a4..5e2f3a7 100644
--- a/ipc/ipc.gyp
+++ b/ipc/ipc.gyp
@@ -18,7 +18,7 @@
},
'dependencies': [
'../base/base.gyp:base',
- # TODO(vtl): Needed for base/lazy_instance.h, which is suspect.
+ # TODO(viettrungluu): Needed for base/lazy_instance.h, which is suspect.
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
],
# TODO(gregoryd): direct_dependent_settings should be shared with the
@@ -151,7 +151,8 @@
},
'dependencies': [
'../base/base.gyp:base_nacl_win64',
- # TODO(vtl): Needed for base/lazy_instance.h, which is suspect.
+ # TODO(viettrungluu): Needed for base/lazy_instance.h, which is
+ # suspect.
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations_win64',
],
# TODO(gregoryd): direct_dependent_settings should be shared with the
diff --git a/ipc/ipc_channel_unittest.cc b/ipc/ipc_channel_unittest.cc
index aa5da15..db9dd3c 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;
}
diff --git a/ipc/ipc_fuzzing_tests.cc b/ipc/ipc_fuzzing_tests.cc
index 080c643..030709e 100644
--- a/ipc/ipc_fuzzing_tests.cc
+++ b/ipc/ipc_fuzzing_tests.cc
@@ -7,11 +7,7 @@
#include <sstream>
#include "base/message_loop.h"
-#include "base/process_util.h"
#include "base/threading/platform_thread.h"
-#include "ipc/ipc_channel.h"
-#include "ipc/ipc_channel_proxy.h"
-#include "ipc/ipc_multiprocess_test.h"
#include "ipc/ipc_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -246,14 +242,16 @@ class FuzzerClientListener : public SimpleListener {
IPC::Message* last_msg_;
};
-// Runs the fuzzing server child mode. Returns when the preset number
-// of messages have been received.
-MULTIPROCESS_IPC_TEST_MAIN(RunFuzzServer) {
+// Runs the fuzzing server child mode. Returns when the preset number of
+// messages have been received.
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(FuzzServerClient) {
MessageLoopForIO main_message_loop;
FuzzerServerListener listener;
- IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_CLIENT, &listener);
- CHECK(chan.Connect());
- listener.Init(&chan);
+ IPC::Channel channel(IPCTestBase::GetChannelName("FuzzServerClient"),
+ IPC::Channel::MODE_CLIENT,
+ &listener);
+ CHECK(channel.Connect());
+ listener.Init(&channel);
MessageLoop::current()->Run();
return 0;
}
@@ -264,76 +262,69 @@ class IPCFuzzingTest : public IPCTestBase {
// This test makes sure that the FuzzerClientListener and FuzzerServerListener
// are working properly by generating two well formed IPC calls.
TEST_F(IPCFuzzingTest, SanityTest) {
+ Init("FuzzServerClient");
+
FuzzerClientListener listener;
- IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
- &listener);
- base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
- ASSERT_TRUE(server_process);
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
- ASSERT_TRUE(chan.Connect());
- listener.Init(&chan);
+ CreateChannel(&listener);
+ listener.Init(channel());
+ ASSERT_TRUE(ConnectChannel());
+ ASSERT_TRUE(StartClient());
IPC::Message* msg = NULL;
int value = 43;
msg = new MsgClassIS(value, L"expect 43");
- chan.Send(msg);
+ sender()->Send(msg);
EXPECT_TRUE(listener.ExpectMessage(value, MsgClassIS::ID));
msg = new MsgClassSI(L"expect 44", ++value);
- chan.Send(msg);
+ sender()->Send(msg);
EXPECT_TRUE(listener.ExpectMessage(value, MsgClassSI::ID));
- EXPECT_TRUE(base::WaitForSingleProcess(
- server_process, base::TimeDelta::FromSeconds(5)));
- base::CloseProcessHandle(server_process);
+ EXPECT_TRUE(WaitForClientShutdown());
+ DestroyChannel();
}
-// This test uses a payload that is smaller than expected.
-// This generates an error while unpacking the IPC buffer which in
-// In debug this triggers an assertion and in release it is ignored(!!). Right
-// after we generate another valid IPC to make sure framing is working
-// properly.
+// This test uses a payload that is smaller than expected. This generates an
+// error while unpacking the IPC buffer which in debug trigger an assertion and
+// in release is ignored (!). Right after we generate another valid IPC to make
+// sure framing is working properly.
#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
TEST_F(IPCFuzzingTest, MsgBadPayloadShort) {
+ Init("FuzzServerClient");
+
FuzzerClientListener listener;
- IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
- &listener);
- base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
- ASSERT_TRUE(server_process);
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
- ASSERT_TRUE(chan.Connect());
- listener.Init(&chan);
+ CreateChannel(&listener);
+ listener.Init(channel());
+ ASSERT_TRUE(ConnectChannel());
+ ASSERT_TRUE(StartClient());
IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassIS::ID,
IPC::Message::PRIORITY_NORMAL);
msg->WriteInt(666);
- chan.Send(msg);
+ sender()->Send(msg);
EXPECT_TRUE(listener.ExpectMsgNotHandled(MsgClassIS::ID));
msg = new MsgClassSI(L"expect one", 1);
- chan.Send(msg);
+ sender()->Send(msg);
EXPECT_TRUE(listener.ExpectMessage(1, MsgClassSI::ID));
- EXPECT_TRUE(base::WaitForSingleProcess(
- server_process, base::TimeDelta::FromSeconds(5)));
- base::CloseProcessHandle(server_process);
+ EXPECT_TRUE(WaitForClientShutdown());
+ DestroyChannel();
}
#endif
-// This test uses a payload that has too many arguments, but so the payload
-// size is big enough so the unpacking routine does not generate an error as
-// in the case of MsgBadPayloadShort test.
-// This test does not pinpoint a flaw (per se) as by design we don't carry
-// type information on the IPC message.
+// This test uses a payload that has too many arguments, but so the payload size
+// is big enough so the unpacking routine does not generate an error as in the
+// case of MsgBadPayloadShort test. This test does not pinpoint a flaw (per se)
+// as by design we don't carry type information on the IPC message.
TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) {
+ Init("FuzzServerClient");
+
FuzzerClientListener listener;
- IPC::Channel chan(kFuzzerChannel, IPC::Channel::MODE_SERVER,
- &listener);
- base::ProcessHandle server_process = SpawnChild(FUZZER_SERVER, &chan);
- ASSERT_TRUE(server_process);
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
- ASSERT_TRUE(chan.Connect());
- listener.Init(&chan);
+ CreateChannel(&listener);
+ listener.Init(channel());
+ ASSERT_TRUE(ConnectChannel());
+ ASSERT_TRUE(StartClient());
IPC::Message* msg = new IPC::Message(MSG_ROUTING_CONTROL, MsgClassSI::ID,
IPC::Message::PRIORITY_NORMAL);
@@ -341,18 +332,17 @@ TEST_F(IPCFuzzingTest, MsgBadPayloadArgs) {
msg->WriteInt(0);
msg->WriteInt(0x65); // Extra argument.
- chan.Send(msg);
+ sender()->Send(msg);
EXPECT_TRUE(listener.ExpectMessage(0, MsgClassSI::ID));
// Now send a well formed message to make sure the receiver wasn't
// thrown out of sync by the extra argument.
msg = new MsgClassIS(3, L"expect three");
- chan.Send(msg);
+ sender()->Send(msg);
EXPECT_TRUE(listener.ExpectMessage(3, MsgClassIS::ID));
- EXPECT_TRUE(base::WaitForSingleProcess(
- server_process, base::TimeDelta::FromSeconds(5)));
- base::CloseProcessHandle(server_process);
+ EXPECT_TRUE(WaitForClientShutdown());
+ DestroyChannel();
}
// This class is for testing the IPC_BEGIN_MESSAGE_MAP_EX macros.
diff --git a/ipc/ipc_multiprocess_test.cc b/ipc/ipc_multiprocess_test.cc
index b13ed7b..8e3c03a 100644
--- a/ipc/ipc_multiprocess_test.cc
+++ b/ipc/ipc_multiprocess_test.cc
@@ -11,9 +11,13 @@
#include "ipc/ipc_descriptors.h"
#endif
+namespace internal {
+
void MultiProcessTestIPCSetUp() {
#if defined(OS_POSIX)
base::GlobalDescriptors::GetInstance()->Set(kPrimaryIPCChannel,
kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
#endif
}
+
+} // namespace internal
diff --git a/ipc/ipc_multiprocess_test.h b/ipc/ipc_multiprocess_test.h
index 3bf2ad8..43aaa6b 100644
--- a/ipc/ipc_multiprocess_test.h
+++ b/ipc/ipc_multiprocess_test.h
@@ -8,15 +8,19 @@
#include "testing/multiprocess_func_list.h"
// Use this macro when your sub-process is using an IPCChannel to communicate
-// with the test process.
-// See comment below for MultiProcessTestIPCSetUp() on why this is needed.
+// with the test process. See the comment below for why this is needed.
#define MULTIPROCESS_IPC_TEST_MAIN(test_main) \
- MULTIPROCESS_TEST_MAIN_WITH_SETUP(test_main, MultiProcessTestIPCSetUp)
+ MULTIPROCESS_TEST_MAIN_WITH_SETUP(test_main, \
+ internal::MultiProcessTestIPCSetUp)
-// Setup function used by MULTIPROCESS_IPC_TEST_MAIN.
-// Registers the IPC channel as a global descriptor in the child process. This
-// is needed on POSIX as the IPCChannel when created looks for a specific global
-// descriptor to establish the connection to the parent process.
+namespace internal {
+
+// Setup function used by MULTIPROCESS_IPC_TEST_MAIN. Registers the IPC channel
+// as a global descriptor in the child process. This is needed on POSIX as on
+// creation the IPCChannel looks for a specific global descriptor to establish
+// the connection to the parent process.
void MultiProcessTestIPCSetUp();
+} // namespace internal
+
#endif // IPC_IPC_MULTIPROCESS_TEST_H_
diff --git a/ipc/ipc_perftests.cc b/ipc/ipc_perftests.cc
index 901f07a..a24c47d 100644
--- a/ipc/ipc_perftests.cc
+++ b/ipc/ipc_perftests.cc
@@ -4,13 +4,6 @@
#include "build/build_config.h"
-#if defined(OS_WIN)
-#include <windows.h>
-#elif defined(OS_POSIX)
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
#include <algorithm>
#include <string>
@@ -26,7 +19,6 @@
#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_test_base.h"
@@ -143,9 +135,9 @@ class ChannelReflectorListener : public IPC::Listener {
EventTimeTracker latency_tracker_;
};
-class ChannelPerfListener : public IPC::Listener {
+class PerformanceChannelListener : public IPC::Listener {
public:
- ChannelPerfListener()
+ PerformanceChannelListener()
: channel_(NULL),
msg_count_(0),
msg_size_(0),
@@ -154,7 +146,7 @@ class ChannelPerfListener : public IPC::Listener {
VLOG(1) << "Server listener up";
}
- ~ChannelPerfListener() {
+ ~PerformanceChannelListener() {
VLOG(1) << "Server listener down";
}
@@ -229,22 +221,21 @@ class ChannelPerfListener : public IPC::Listener {
};
TEST_F(IPCChannelPerfTest, Performance) {
- // Setup IPC channel.
- ChannelPerfListener perf_listener;
- IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_SERVER,
- &perf_listener);
- perf_listener.Init(&chan);
- ASSERT_TRUE(chan.Connect());
+ Init("PerformanceClient");
- base::ProcessHandle process_handle = SpawnChild(TEST_REFLECTOR, &chan);
- ASSERT_TRUE(process_handle);
+ // Set up IPC channel and start client.
+ PerformanceChannelListener listener;
+ CreateChannel(&listener);
+ listener.Init(channel());
+ ASSERT_TRUE(ConnectChannel());
+ ASSERT_TRUE(StartClient());
const size_t kMsgSizeBase = 12;
const int kMsgSizeMaxExp = 5;
int msg_count = 100000;
size_t msg_size = kMsgSizeBase;
for (int i = 1; i <= kMsgSizeMaxExp; i++) {
- perf_listener.SetTestParams(msg_count, msg_size);
+ listener.SetTestParams(msg_count, msg_size);
// This initial message will kick-start the ping-pong of messages.
IPC::Message* message =
@@ -252,7 +243,7 @@ TEST_F(IPCChannelPerfTest, Performance) {
message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
message->WriteInt(-1);
message->WriteString("hello");
- chan.Send(message);
+ sender()->Send(message);
// Run message loop.
MessageLoop::current()->Run();
@@ -265,22 +256,21 @@ TEST_F(IPCChannelPerfTest, Performance) {
message->WriteInt64(base::TimeTicks::Now().ToInternalValue());
message->WriteInt(-1);
message->WriteString("quit");
- chan.Send(message);
+ sender()->Send(message);
- // Clean up child process.
- EXPECT_TRUE(base::WaitForSingleProcess(process_handle,
- base::TimeDelta::FromSeconds(5)));
- base::CloseProcessHandle(process_handle);
+ EXPECT_TRUE(WaitForClientShutdown());
+ DestroyChannel();
}
// This message loop bounces all messages back to the sender.
-MULTIPROCESS_IPC_TEST_MAIN(RunReflector) {
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(PerformanceClient) {
MessageLoopForIO main_message_loop;
- ChannelReflectorListener channel_reflector_listener;
- IPC::Channel chan(kReflectorChannel, IPC::Channel::MODE_CLIENT,
- &channel_reflector_listener);
- channel_reflector_listener.Init(&chan);
- CHECK(chan.Connect());
+ ChannelReflectorListener listener;
+ IPC::Channel channel(IPCTestBase::GetChannelName("PerformanceClient"),
+ IPC::Channel::MODE_CLIENT,
+ &listener);
+ listener.Init(&channel);
+ CHECK(channel.Connect());
MessageLoop::current()->Run();
return 0;
diff --git a/ipc/ipc_send_fds_test.cc b/ipc/ipc_send_fds_test.cc
index 005103c..5699e6d 100644
--- a/ipc/ipc_send_fds_test.cc
+++ b/ipc/ipc_send_fds_test.cc
@@ -4,6 +4,7 @@
#include "build/build_config.h"
+#if defined(OS_POSIX)
#if defined(OS_MACOSX)
extern "C" {
#include <sandbox.h>
@@ -11,18 +12,15 @@ extern "C" {
#endif
#include <fcntl.h>
#include <sys/stat.h>
+#include <unistd.h>
+#include "base/file_descriptor_posix.h"
#include "base/message_loop.h"
+#include "base/pickle.h"
#include "base/posix/eintr_wrapper.h"
-#include "ipc/ipc_channel.h"
-#include "ipc/ipc_listener.h"
#include "ipc/ipc_message_utils.h"
-#include "ipc/ipc_multiprocess_test.h"
#include "ipc/ipc_test_base.h"
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-
namespace {
const unsigned kNumFDsToSend = 20;
@@ -33,21 +31,21 @@ static void VerifyAndCloseDescriptor(int fd, ino_t inode_num) {
char buf;
ssize_t amt_read = read(fd, &buf, 1);
ASSERT_EQ(amt_read, 1);
- ASSERT_EQ(buf, 0); // /dev/zero always reads NUL bytes.
+ ASSERT_EQ(buf, 0); // /dev/zero always reads 0 bytes.
struct stat st;
ASSERT_EQ(fstat(fd, &st), 0);
ASSERT_EQ(close(fd), 0);
- // We compare iNode numbers to check that the file sent over the wire
- // was actually the same physical file as the one we were expecting.
+ // Compare inode numbers to check that the file sent over the wire is actually
+ // the one expected.
ASSERT_EQ(inode_num, st.st_ino);
}
class MyChannelDescriptorListener : public IPC::Listener {
public:
- MyChannelDescriptorListener(ino_t expected_inode_num)
+ explicit MyChannelDescriptorListener(ino_t expected_inode_num)
: expected_inode_num_(expected_inode_num),
num_fds_received_(0) {}
@@ -57,13 +55,12 @@ class MyChannelDescriptorListener : public IPC::Listener {
++num_fds_received_;
base::FileDescriptor descriptor;
- IPC::ParamTraits<base::FileDescriptor>::Read(
- &message, &iter, &descriptor);
+ IPC::ParamTraits<base::FileDescriptor>::Read(&message, &iter, &descriptor);
VerifyAndCloseDescriptor(descriptor.fd, expected_inode_num_);
- if (num_fds_received_ == kNumFDsToSend) {
+ if (num_fds_received_ == kNumFDsToSend)
MessageLoop::current()->Quit();
- }
+
return true;
}
@@ -71,8 +68,8 @@ class MyChannelDescriptorListener : public IPC::Listener {
MessageLoop::current()->Quit();
}
- bool GotExpectedNumberOfDescriptors() {
- return kNumFDsToSend == num_fds_received_;
+ bool GotExpectedNumberOfDescriptors() const {
+ return num_fds_received_ == kNumFDsToSend;
}
private:
@@ -80,126 +77,107 @@ class MyChannelDescriptorListener : public IPC::Listener {
unsigned num_fds_received_;
};
-void TestDescriptorServer(IPC::Channel& chan,
- base::ProcessHandle process_handle) {
- ASSERT_TRUE(process_handle);
+class IPCSendFdsTest : public IPCTestBase {
+ protected:
+ void RunServer() {
+ // Set up IPC channel and start client.
+ MyChannelDescriptorListener listener(-1);
+ CreateChannel(&listener);
+ ASSERT_TRUE(ConnectChannel());
+ ASSERT_TRUE(StartClient());
+
+ for (unsigned i = 0; i < kNumFDsToSend; ++i) {
+ const int fd = open(kDevZeroPath, O_RDONLY);
+ ASSERT_GE(fd, 0);
+ base::FileDescriptor descriptor(fd, true);
+
+ IPC::Message* message =
+ new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL);
+ IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
+ ASSERT_TRUE(sender()->Send(message));
+ }
- for (unsigned i = 0; i < kNumFDsToSend; ++i) {
- base::FileDescriptor descriptor;
- const int fd = open(kDevZeroPath, O_RDONLY);
- ASSERT_GE(fd, 0);
- descriptor.auto_close = true;
- descriptor.fd = fd;
-
- IPC::Message* message = new IPC::Message(0, // routing_id
- 3, // message type
- IPC::Message::PRIORITY_NORMAL);
- IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
- ASSERT_TRUE(chan.Send(message));
- }
+ // Run message loop.
+ MessageLoop::current()->Run();
- // Run message loop.
- MessageLoop::current()->Run();
+ // Close the channel so the client's OnChannelError() gets fired.
+ channel()->Close();
- // Close Channel so client gets its OnChannelError() callback fired.
- chan.Close();
+ EXPECT_TRUE(WaitForClientShutdown());
+ DestroyChannel();
+ }
+};
- // Cleanup child process.
- EXPECT_TRUE(base::WaitForSingleProcess(
- process_handle, base::TimeDelta::FromSeconds(5)));
+TEST_F(IPCSendFdsTest, DescriptorTest) {
+ Init("SendFdsClient");
+ RunServer();
}
-int TestDescriptorClient(ino_t expected_inode_num) {
+int SendFdsClientCommon(const std::string& test_client_name,
+ ino_t expected_inode_num) {
MessageLoopForIO main_message_loop;
MyChannelDescriptorListener listener(expected_inode_num);
- // Setup IPC channel.
- IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_CLIENT,
- &listener);
- CHECK(chan.Connect());
+ // Set up IPC channel.
+ IPC::Channel channel(IPCTestBase::GetChannelName(test_client_name),
+ IPC::Channel::MODE_CLIENT,
+ &listener);
+ CHECK(channel.Connect());
- // Run message loop so IPC Channel can handle message IO.
+ // Run message loop.
MessageLoop::current()->Run();
- // Verify that the message loop was exited due to getting the correct
- // number of descriptors, and not because the channel closing unexpectedly.
+ // Verify that the message loop was exited due to getting the correct number
+ // of descriptors, and not because of the channel closing unexpectedly.
CHECK(listener.GotExpectedNumberOfDescriptors());
return 0;
}
-class IPCSendFdsTest : public IPCTestBase {
-};
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsClient) {
+ struct stat st;
+ int fd = open(kDevZeroPath, O_RDONLY);
+ fstat(fd, &st);
+ EXPECT_GE(HANDLE_EINTR(close(fd)), 0);
+ return SendFdsClientCommon("SendFdsClient", st.st_ino);
+}
#if defined(OS_MACOSX)
+// Test that FDs are correctly sent to a sandboxed process.
// TODO(port): Make this test cross-platform.
-MULTIPROCESS_IPC_TEST_MAIN(RunTestDescriptorClientSandboxed) {
+TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) {
+ Init("SendFdsSandboxedClient");
+ RunServer();
+}
+
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SendFdsSandboxedClient) {
struct stat st;
const int fd = open(kDevZeroPath, O_RDONLY);
fstat(fd, &st);
- if (HANDLE_EINTR(close(fd)) < 0) {
+ if (HANDLE_EINTR(close(fd)) < 0)
return -1;
- }
- // Enable the Sandbox.
+ // Enable the sandbox.
char* error_buff = NULL;
int error = sandbox_init(kSBXProfilePureComputation, SANDBOX_NAMED,
&error_buff);
bool success = (error == 0 && error_buff == NULL);
- if (!success) {
+ if (!success)
return -1;
- }
sandbox_free_error(error_buff);
- // Make sure Sandbox is really enabled.
+ // Make sure sandbox is really enabled.
if (open(kDevZeroPath, O_RDONLY) != -1) {
LOG(ERROR) << "Sandbox wasn't properly enabled";
return -1;
}
// See if we can receive a file descriptor.
- return TestDescriptorClient(st.st_ino);
-}
-
-// Test that FDs are correctly sent to a sandboxed process.
-TEST_F(IPCSendFdsTest, DescriptorTestSandboxed) {
- // Setup IPC channel.
- MyChannelDescriptorListener listener(-1);
-
- IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
- &listener);
- ASSERT_TRUE(chan.Connect());
-
- base::ProcessHandle process_handle = SpawnChild(
- TEST_DESCRIPTOR_CLIENT_SANDBOXED,
- &chan);
- TestDescriptorServer(chan, process_handle);
+ return SendFdsClientCommon("SendFdsSandboxedClient", st.st_ino);
}
#endif // defined(OS_MACOSX)
-MULTIPROCESS_IPC_TEST_MAIN(RunTestDescriptorClient) {
- struct stat st;
- const int fd = open(kDevZeroPath, O_RDONLY);
- fstat(fd, &st);
- EXPECT_GE(HANDLE_EINTR(close(fd)), 0);
-
- return TestDescriptorClient(st.st_ino);
-}
-
-TEST_F(IPCSendFdsTest, DescriptorTest) {
- // Setup IPC channel.
- MyChannelDescriptorListener listener(-1);
-
- IPC::Channel chan(kTestClientChannel, IPC::Channel::MODE_SERVER,
- &listener);
- ASSERT_TRUE(chan.Connect());
-
- base::ProcessHandle process_handle = SpawnChild(TEST_DESCRIPTOR_CLIENT,
- &chan);
- TestDescriptorServer(chan, process_handle);
-}
-
} // namespace
#endif // defined(OS_POSIX)
diff --git a/ipc/ipc_test_base.cc b/ipc/ipc_test_base.cc
index 7503375..2f739f1 100644
--- a/ipc/ipc_test_base.cc
+++ b/ipc/ipc_test_base.cc
@@ -4,15 +4,6 @@
#include "build/build_config.h"
-#if defined(OS_WIN)
-#include <windows.h>
-#elif defined(OS_POSIX)
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-#include <utility>
-
#include "ipc/ipc_test_base.h"
#include "base/command_line.h"
@@ -20,101 +11,112 @@
#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"
-const char kTestClientChannel[] = "T1";
-const char kReflectorChannel[] = "T2";
-const char kFuzzerChannel[] = "F3";
-const char kSyncSocketChannel[] = "S4";
+// static
+std::string IPCTestBase::GetChannelName(const std::string& test_client_name) {
+ DCHECK(!test_client_name.empty());
+ return test_client_name + "__Channel";
+}
+
+IPCTestBase::IPCTestBase()
+ : client_process_(base::kNullProcessHandle) {
+}
+
+IPCTestBase::~IPCTestBase() {
+}
void IPCTestBase::SetUp() {
MultiProcessTest::SetUp();
// Construct a fresh IO Message loop for the duration of each test.
- message_loop_ = new MessageLoopForIO();
+ DCHECK(!message_loop_.get());
+ message_loop_.reset(new MessageLoopForIO());
}
void IPCTestBase::TearDown() {
- delete message_loop_;
- message_loop_ = NULL;
-
+ DCHECK(message_loop_.get());
+ message_loop_.reset();
MultiProcessTest::TearDown();
}
-#if defined(OS_WIN)
-base::ProcessHandle IPCTestBase::SpawnChild(IPCTestBase::ChildType child_type,
- IPC::Channel* channel) {
- // kDebugChildren support.
- bool debug_on_start =
- CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren);
+void IPCTestBase::Init(const std::string& test_client_name) {
+ DCHECK(!test_client_name.empty());
+ DCHECK(test_client_name_.empty());
+ test_client_name_ = test_client_name;
+}
- switch (child_type) {
- case TEST_CLIENT:
- return MultiProcessTest::SpawnChild("RunTestClient", debug_on_start);
- case TEST_REFLECTOR:
- return MultiProcessTest::SpawnChild("RunReflector", debug_on_start);
- case FUZZER_SERVER:
- return MultiProcessTest::SpawnChild("RunFuzzServer", debug_on_start);
- case SYNC_SOCKET_SERVER:
- return MultiProcessTest::SpawnChild("RunSyncSocketServer", debug_on_start);
- default:
- return NULL;
- }
+void IPCTestBase::CreateChannel(IPC::Listener* listener) {
+ return CreateChannelFromChannelHandle(GetChannelName(test_client_name_),
+ listener);
}
-#elif defined(OS_POSIX)
-base::ProcessHandle IPCTestBase::SpawnChild(IPCTestBase::ChildType child_type,
- IPC::Channel* channel) {
- // kDebugChildren support.
+
+bool IPCTestBase::ConnectChannel() {
+ CHECK(channel_.get());
+ return channel_->Connect();
+}
+
+void IPCTestBase::DestroyChannel() {
+ DCHECK(channel_.get());
+ channel_.reset();
+}
+
+void IPCTestBase::CreateChannelFromChannelHandle(
+ const IPC::ChannelHandle& channel_handle,
+ IPC::Listener* listener) {
+ CHECK(!channel_.get());
+ CHECK(!channel_proxy_.get());
+ channel_.reset(new IPC::Channel(channel_handle,
+ IPC::Channel::MODE_SERVER,
+ listener));
+}
+
+void IPCTestBase::CreateChannelProxy(
+ IPC::Listener* listener,
+ base::SingleThreadTaskRunner* ipc_task_runner) {
+ CHECK(!channel_.get());
+ CHECK(!channel_proxy_.get());
+ channel_proxy_.reset(new IPC::ChannelProxy(GetChannelName(test_client_name_),
+ IPC::Channel::MODE_SERVER,
+ listener,
+ ipc_task_runner));
+}
+
+void IPCTestBase::DestroyChannelProxy() {
+ CHECK(channel_proxy_.get());
+ channel_proxy_.reset();
+}
+
+bool IPCTestBase::StartClient() {
+ DCHECK(client_process_ == base::kNullProcessHandle);
+
+ std::string test_main = test_client_name_ + "TestClientMain";
bool debug_on_start =
CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren);
+#if defined(OS_WIN)
+ client_process_ = MultiProcessTest::SpawnChild(test_main, debug_on_start);
+#elif defined(OS_POSIX)
base::FileHandleMappingVector fds_to_map;
- const int ipcfd = channel->GetClientFileDescriptor();
- if (ipcfd > -1) {
+ const int ipcfd = channel_.get() ? channel_->GetClientFileDescriptor() :
+ channel_proxy_->GetClientFileDescriptor();
+ if (ipcfd > -1)
fds_to_map.push_back(std::pair<int, int>(ipcfd, kPrimaryIPCChannel + 3));
- }
-
- base::ProcessHandle ret = base::kNullProcessHandle;
- switch (child_type) {
- case TEST_CLIENT:
- ret = MultiProcessTest::SpawnChild("RunTestClient",
- fds_to_map,
- debug_on_start);
- break;
- case TEST_DESCRIPTOR_CLIENT:
- ret = MultiProcessTest::SpawnChild("RunTestDescriptorClient",
- fds_to_map,
- debug_on_start);
- break;
- case TEST_DESCRIPTOR_CLIENT_SANDBOXED:
- ret = MultiProcessTest::SpawnChild("RunTestDescriptorClientSandboxed",
- fds_to_map,
- debug_on_start);
- break;
- case TEST_REFLECTOR:
- ret = MultiProcessTest::SpawnChild("RunReflector",
- fds_to_map,
- debug_on_start);
- break;
- case FUZZER_SERVER:
- ret = MultiProcessTest::SpawnChild("RunFuzzServer",
- fds_to_map,
- debug_on_start);
- break;
- case SYNC_SOCKET_SERVER:
- ret = MultiProcessTest::SpawnChild("RunSyncSocketServer",
- fds_to_map,
- debug_on_start);
- break;
- default:
- return base::kNullProcessHandle;
- break;
- }
- return ret;
+
+ client_process_ = MultiProcessTest::SpawnChild(test_main,
+ fds_to_map,
+ debug_on_start);
+#endif
+
+ return client_process_ != base::kNullProcessHandle;
+}
+
+bool IPCTestBase::WaitForClientShutdown() {
+ DCHECK(client_process_ != base::kNullProcessHandle);
+
+ bool rv = base::WaitForSingleProcess(client_process_,
+ base::TimeDelta::FromSeconds(5));
+ base::CloseProcessHandle(client_process_);
+ client_process_ = base::kNullProcessHandle;
+ return rv;
}
-#endif // defined(OS_POSIX)
diff --git a/ipc/ipc_test_base.h b/ipc/ipc_test_base.h
index 08d410c..2afb720 100644
--- a/ipc/ipc_test_base.h
+++ b/ipc/ipc_test_base.h
@@ -5,42 +5,95 @@
#ifndef IPC_IPC_TEST_BASE_H_
#define IPC_IPC_TEST_BASE_H_
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
#include "base/process.h"
#include "base/test/multiprocess_test.h"
-
-// The different channel names for the child processes.
-extern const char kTestClientChannel[];
-extern const char kReflectorChannel[];
-extern const char kFuzzerChannel[];
-extern const char kSyncSocketChannel[];
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_proxy.h"
+#include "ipc/ipc_multiprocess_test.h"
class MessageLoopForIO;
-namespace IPC {
-class Channel;
-} // namespace IPC
-// Base class to facilitate spawning IPC client processes.
+// A test fixture for multiprocess IPC tests. Such tests include a "client" side
+// (running in a separate process). The same client may be shared between
+// several different tests.
class IPCTestBase : public base::MultiProcessTest {
public:
- enum ChildType {
- TEST_CLIENT,
- TEST_DESCRIPTOR_CLIENT,
- TEST_DESCRIPTOR_CLIENT_SANDBOXED,
- TEST_REFLECTOR,
- FUZZER_SERVER,
- SYNC_SOCKET_SERVER
- };
+ // The channel name is based on the client's name. This is a public static
+ // helper to be used by the client-side code; server-side test code should
+ // usually not use this (directly).
+ static std::string GetChannelName(const std::string& test_client_name);
protected:
- // Create a new MessageLoopForIO for each test.
+ IPCTestBase();
+ virtual ~IPCTestBase();
+
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
- // Spawns a child process of the specified type
- base::ProcessHandle SpawnChild(ChildType child_type, IPC::Channel* channel);
+ // Initializes the test to use the given client.
+ void Init(const std::string& test_client_name);
+
+ // Creates a channel with the given listener and connects to the channel
+ // (returning true if successful), respectively. Use these to use a channel
+ // directly. Since the listener must outlive the channel, you must destroy the
+ // channel before the listener gets destroyed.
+ void CreateChannel(IPC::Listener* listener);
+ bool ConnectChannel();
+ void DestroyChannel();
+
+ // Use this instead of CreateChannel() if you want to use some different
+ // channel specification (then use ConnectChannel() as usual).
+ void CreateChannelFromChannelHandle(const IPC::ChannelHandle& channel_handle,
+ IPC::Listener* listener);
+
+ // Creates a channel proxy with the given listener and task runner. (The
+ // channel proxy will automatically create and connect a channel.) You must
+ // (manually) destroy the channel proxy before the task runner's thread is
+ // destroyed.
+ void CreateChannelProxy(IPC::Listener* listener,
+ base::SingleThreadTaskRunner* ipc_task_runner);
+ void DestroyChannelProxy();
+
+ // Starts the client process, returning true if successful; this should be
+ // done after connecting to the channel.
+ bool StartClient();
+
+ // Waits for the client to shut down, returning true if successful. Note that
+ // this does not initiate client shutdown; that must be done by the test
+ // (somehow). This must be called before the end of the test whenever
+ // StartClient() was called successfully.
+ bool WaitForClientShutdown();
- // Created around each test instantiation.
- MessageLoopForIO* message_loop_;
+ // Use this to send IPC messages (when you don't care if you're using a
+ // channel or a proxy).
+ IPC::Sender* sender() {
+ return channel_.get() ? static_cast<IPC::Sender*>(channel_.get()) :
+ static_cast<IPC::Sender*>(channel_proxy_.get());
+ }
+
+ IPC::Channel* channel() { return channel_.get(); }
+ IPC::ChannelProxy* channel_proxy() { return channel_proxy_.get(); }
+
+ const base::ProcessHandle& client_process() const { return client_process_; }
+
+ private:
+ std::string test_client_name_;
+ scoped_ptr<MessageLoopForIO> message_loop_;
+
+ scoped_ptr<IPC::Channel> channel_;
+ scoped_ptr<IPC::ChannelProxy> channel_proxy_;
+
+ base::ProcessHandle client_process_;
+
+ DISALLOW_COPY_AND_ASSIGN(IPCTestBase);
};
+// Use this to declare the client side for tests using IPCTestBase.
+#define MULTIPROCESS_IPC_TEST_CLIENT_MAIN(test_client_name) \
+ MULTIPROCESS_IPC_TEST_MAIN(test_client_name ## TestClientMain)
+
#endif // IPC_IPC_TEST_BASE_H_
diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc
index 4dba55d..57ba326 100644
--- a/ipc/sync_socket_unittest.cc
+++ b/ipc/sync_socket_unittest.cc
@@ -12,8 +12,6 @@
#include "base/message_loop.h"
#include "base/process_util.h"
#include "base/threading/thread.h"
-#include "ipc/ipc_channel_proxy.h"
-#include "ipc/ipc_multiprocess_test.h"
#include "ipc/ipc_test_base.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -106,14 +104,16 @@ class SyncSocketServerListener : public IPC::Listener {
DISALLOW_COPY_AND_ASSIGN(SyncSocketServerListener);
};
-// Runs the fuzzing server child mode. Returns when the preset number
-// of messages have been received.
-MULTIPROCESS_IPC_TEST_MAIN(RunSyncSocketServer) {
+// Runs the fuzzing server child mode. Returns when the preset number of
+// messages have been received.
+MULTIPROCESS_IPC_TEST_CLIENT_MAIN(SyncSocketServerClient) {
MessageLoopForIO main_message_loop;
SyncSocketServerListener listener;
- IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_CLIENT, &listener);
- EXPECT_TRUE(chan.Connect());
- listener.Init(&chan);
+ IPC::Channel channel(IPCTestBase::GetChannelName("SyncSocketServerClient"),
+ IPC::Channel::MODE_CLIENT,
+ &listener);
+ EXPECT_TRUE(channel.Connect());
+ listener.Init(&channel);
MessageLoop::current()->Run();
return 0;
}
@@ -167,11 +167,11 @@ class SyncSocketTest : public IPCTestBase {
};
TEST_F(SyncSocketTest, SanityTest) {
+ Init("SyncSocketServerClient");
+
SyncSocketClientListener listener;
- IPC::Channel chan(kSyncSocketChannel, IPC::Channel::MODE_SERVER,
- &listener);
- base::ProcessHandle server_process = SpawnChild(SYNC_SOCKET_SERVER, &chan);
- ASSERT_TRUE(server_process);
+ CreateChannel(&listener);
+ ASSERT_TRUE(StartClient());
// Create a pair of SyncSockets.
base::SyncSocket pair[2];
base::SyncSocket::CreatePair(&pair[0], &pair[1]);
@@ -180,12 +180,12 @@ TEST_F(SyncSocketTest, SanityTest) {
EXPECT_EQ(0U, pair[1].Peek());
base::SyncSocket::Handle target_handle;
// Connect the channel and listener.
- ASSERT_TRUE(chan.Connect());
- listener.Init(&pair[0], &chan);
+ ASSERT_TRUE(ConnectChannel());
+ listener.Init(&pair[0], channel());
#if defined(OS_WIN)
// On windows we need to duplicate the handle into the server process.
BOOL retval = DuplicateHandle(GetCurrentProcess(), pair[1].handle(),
- server_process, &target_handle,
+ client_process(), &target_handle,
0, FALSE, DUPLICATE_SAME_ACCESS);
EXPECT_TRUE(retval);
// Set up a message to pass the handle to the server.
@@ -196,18 +196,16 @@ TEST_F(SyncSocketTest, SanityTest) {
base::FileDescriptor filedesc(target_handle, false);
IPC::Message* msg = new MsgClassSetHandle(filedesc);
#endif // defined(OS_WIN)
- EXPECT_TRUE(chan.Send(msg));
+ EXPECT_TRUE(sender()->Send(msg));
// Use the current thread as the I/O thread.
MessageLoop::current()->Run();
// Shut down.
pair[0].Close();
pair[1].Close();
- EXPECT_TRUE(base::WaitForSingleProcess(
- server_process, base::TimeDelta::FromSeconds(5)));
- base::CloseProcessHandle(server_process);
+ EXPECT_TRUE(WaitForClientShutdown());
+ DestroyChannel();
}
-
// A blocking read operation that will block the thread until it receives
// |length| bytes of packets or Shutdown() is called on another thread.
static void BlockingRead(base::SyncSocket* socket, char* buf,