Refactor (many) IPC tests, notably most of the multiprocess tests.

This factors out common code and, more importantly/usefully, makes test-specific
code more local, and thus easier to add new tests and maintain existing ones. In
particular, this allows you to add a new test "client" (running in another
process) without modifying ipc_test_base.*.

Review URL: https://codereview.chromium.org/12051048

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@178901 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 3c78858906d3d0d7f5319d7c993240284b4503b5
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,35 +6,89 @@
 
 #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;
 
+static void Send(IPC::Sender* sender, const char* text) {
+  static int message_index = 0;
+
+  IPC::Message* message = new IPC::Message(0,
+                                           2,
+                                           IPC::Message::PRIORITY_NORMAL);
+  message->WriteInt(message_index++);
+  message->WriteString(std::string(text));
+
+  // Make sure we can handle large messages.
+  char junk[kLongMessageStringNumBytes];
+  memset(junk, 'a', sizeof(junk)-1);
+  junk[sizeof(junk)-1] = 0;
+  message->WriteString(std::string(junk));
+
+  // DEBUG: printf("[%u] sending message [%s]\n", GetCurrentProcessId(), text);
+  sender->Send(message);
+}
+
+// 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:
+  GenericChannelListener() : sender_(NULL), messages_left_(50) {}
+  virtual ~GenericChannelListener() {}
+
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+    PickleIterator iter(message);
+
+    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;
+  }
+
+  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();
+  }
+
+  void Init(IPC::Sender* s) {
+    sender_ = s;
+  }
+
+ protected:
+  void SendNextMessage() {
+    if (--messages_left_ <= 0)
+      MessageLoop::current()->Quit();
+    else
+      Send(sender_, "Foo");
+  }
+
+ private:
+  IPC::Sender* sender_;
+  int messages_left_;
+};
+
 class IPCChannelTest : public IPCTestBase {
 };
 
+// TODO(viettrungluu): Move to a separate IPCMessageTest.
 TEST_F(IPCChannelTest, BasicMessageTest) {
   int v1 = 10;
   std::string v2("foobar");
@@ -66,220 +120,103 @@
   EXPECT_FALSE(m.ReadWString(&iter, &vw));
 }
 
-static void Send(IPC::Sender* sender, const char* text) {
-  static int message_index = 0;
-
-  IPC::Message* message = new IPC::Message(0,
-                                           2,
-                                           IPC::Message::PRIORITY_NORMAL);
-  message->WriteInt(message_index++);
-  message->WriteString(std::string(text));
-
-  // Make sure we can handle large messages.
-  char junk[kLongMessageStringNumBytes];
-  memset(junk, 'a', sizeof(junk)-1);
-  junk[sizeof(junk)-1] = 0;
-  message->WriteString(std::string(junk));
-
-  // DEBUG: printf("[%u] sending message [%s]\n", GetCurrentProcessId(), text);
-  sender->Send(message);
-}
-
-class MyChannelListener : public IPC::Listener {
- public:
-  virtual bool OnMessageReceived(const IPC::Message& message) {
-    PickleIterator iter(message);
-
-    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());
-
-
-    if (--messages_left_ == 0) {
-      MessageLoop::current()->Quit();
-    } else {
-      Send(sender_, "Foo");
-    }
-    return true;
-  }
-
-  virtual void OnChannelError() {
-    // There is a race when closing the channel so the last message may be lost.
-    EXPECT_LE(messages_left_, 1);
-    MessageLoop::current()->Quit();
-  }
-
-  void Init(IPC::Sender* s) {
-    sender_ = s;
-    messages_left_ = 50;
-  }
-
- private:
-  IPC::Sender* sender_;
-  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());
+  Init("GenericClient");
 
-  channel_listener.Init(&chan);
+  // Set up IPC channel and start client.
+  GenericChannelListener listener;
+  CreateChannel(&listener);
+  listener.Init(sender());
+  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();
 }
 
+// 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));
-    }
+  ASSERT_TRUE(StartClient());
 
-    base::ProcessHandle process_handle = MultiProcessTest::SpawnChild(
-        "RunTestClient",
-        fds_to_map,
-        debug_on_start);
-#endif  // defined(OS_POSIX)
+  Send(sender(), "hello from parent");
 
-    ASSERT_TRUE(process_handle);
+  // Run message loop.
+  MessageLoop::current()->Run();
 
-    Send(&chan, "hello from parent");
+  EXPECT_TRUE(WaitForClientShutdown());
 
-    // run message loop
-    MessageLoop::current()->Run();
-
-    // cleanup child process
-    EXPECT_TRUE(base::WaitForSingleProcess(
-        process_handle, base::TimeDelta::FromSeconds(5)));
-    base::CloseProcessHandle(process_handle);
-  }
+  // Destroy the channel proxy before shutting down the thread.
+  DestroyChannelProxy();
   thread.Stop();
 }
 
-class ChannelListenerWithOnConnectedSend : public IPC::Listener {
+class ChannelListenerWithOnConnectedSend : public GenericChannelListener {
  public:
+  ChannelListenerWithOnConnectedSend() {}
+  virtual ~ChannelListenerWithOnConnectedSend() {}
+
   virtual void OnChannelConnected(int32 peer_pid) OVERRIDE {
     SendNextMessage();
   }
-
-  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
-    PickleIterator iter(message);
-
-    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;
-  }
-
-  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();
-  }
-
-  void Init(IPC::Sender* s) {
-    sender_ = s;
-    messages_left_ = 50;
-  }
-
- private:
-  void SendNextMessage() {
-    if (--messages_left_ == 0) {
-      MessageLoop::current()->Quit();
-    } else {
-      Send(sender_, "Foo");
-    }
-  }
-
-  IPC::Sender* sender_;
-  int messages_left_;
 };
 
 #if defined(OS_WIN)
@@ -288,45 +225,42 @@
 #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.
+  Init("GenericClient");
 
-  ChannelListenerWithOnConnectedSend channel_listener;
-  // Setup IPC channel.
-  IPC::Channel channel(kTestClientChannel, IPC::Channel::MODE_SERVER,
-                       &channel_listener);
-  channel_listener.Init(&channel);
-  ASSERT_TRUE(channel.Connect());
+  // Set up IPC channel and start client.
+  ChannelListenerWithOnConnectedSend listener;
+  CreateChannel(&listener);
+  listener.Init(sender());
+  ASSERT_TRUE(ConnectChannel());
+  ASSERT_TRUE(StartClient());
 
-  base::ProcessHandle process_handle = SpawnChild(TEST_CLIENT, &channel);
-  ASSERT_TRUE(process_handle);
-
-  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;
+  GenericChannelListener 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
+  // 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 @@
   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 @@
 // 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 @@
   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 @@
   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 @@
     VLOG(1) << "Server listener up";
   }
 
-  ~ChannelPerfListener() {
+  ~PerformanceChannelListener() {
     VLOG(1) << "Server listener down";
   }
 
@@ -229,22 +221,21 @@
 };
 
 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 @@
     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 @@
   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,17 +12,14 @@
 #endif
 #include <fcntl.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
-#include "base/message_loop.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"
+#include "base/message_loop.h"
+#include "base/pickle.h"
+#include "base/posix/eintr_wrapper.h"
+#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_test_base.h"
 
 namespace {
 
@@ -33,21 +31,21 @@
   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 @@
     ++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 @@
     MessageLoop::current()->Quit();
   }
 
-  bool GotExpectedNumberOfDescriptors() {
-    return kNumFDsToSend == num_fds_received_;
+  bool GotExpectedNumberOfDescriptors() const {
+    return num_fds_received_ == kNumFDsToSend;
   }
 
  private:
@@ -80,126 +77,107 @@
   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) {
-    base::FileDescriptor descriptor;
-    const int fd = open(kDevZeroPath, O_RDONLY);
-    ASSERT_GE(fd, 0);
-    descriptor.auto_close = true;
-    descriptor.fd = fd;
+    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, // routing_id
-                                             3, // message type
-                                             IPC::Message::PRIORITY_NORMAL);
-    IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
-    ASSERT_TRUE(chan.Send(message));
+      IPC::Message* message =
+          new IPC::Message(0, 3, IPC::Message::PRIORITY_NORMAL);
+      IPC::ParamTraits<base::FileDescriptor>::Write(message, descriptor);
+      ASSERT_TRUE(sender()->Send(message));
+    }
+
+    // Run message loop.
+    MessageLoop::current()->Run();
+
+    // Close the channel so the client's OnChannelError() gets fired.
+    channel()->Close();
+
+    EXPECT_TRUE(WaitForClientShutdown());
+    DestroyChannel();
   }
+};
+
+TEST_F(IPCSendFdsTest, DescriptorTest) {
+  Init("SendFdsClient");
+  RunServer();
+}
+
+int SendFdsClientCommon(const std::string& test_client_name,
+                        ino_t expected_inode_num) {
+  MessageLoopForIO main_message_loop;
+  MyChannelDescriptorListener listener(expected_inode_num);
+
+  // Set up IPC channel.
+  IPC::Channel channel(IPCTestBase::GetChannelName(test_client_name),
+                       IPC::Channel::MODE_CLIENT,
+                       &listener);
+  CHECK(channel.Connect());
 
   // Run message loop.
   MessageLoop::current()->Run();
 
-  // Close Channel so client gets its OnChannelError() callback fired.
-  chan.Close();
-
-  // Cleanup child process.
-  EXPECT_TRUE(base::WaitForSingleProcess(
-      process_handle, base::TimeDelta::FromSeconds(5)));
-}
-
-int TestDescriptorClient(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());
-
-  // Run message loop so IPC Channel can handle message IO.
-  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();
 }
 
+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;
+}
+
+void IPCTestBase::CreateChannel(IPC::Listener* listener) {
+  return CreateChannelFromChannelHandle(GetChannelName(test_client_name_),
+                                        listener);
+}
+
+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)
-base::ProcessHandle IPCTestBase::SpawnChild(IPCTestBase::ChildType child_type,
-                                            IPC::Channel* channel) {
-  // kDebugChildren support.
-  bool debug_on_start =
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren);
-
-  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;
-  }
-}
+  client_process_ = MultiProcessTest::SpawnChild(test_main, debug_on_start);
 #elif defined(OS_POSIX)
-base::ProcessHandle IPCTestBase::SpawnChild(IPCTestBase::ChildType child_type,
-                                            IPC::Channel* channel) {
-  // kDebugChildren support.
-  bool debug_on_start =
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren);
-
   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;
 }
-#endif  // defined(OS_POSIX)
+
+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;
+}
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);
 
-  // Created around each test instantiation.
-  MessageLoopForIO* message_loop_;
+  // 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();
+
+  // 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 @@
   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 @@
 };
 
 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 @@
   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 @@
   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,