Home | History | Annotate | Download | only in ipc
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "build/build_config.h"
      6 
      7 #include "ipc/ipc_test_base.h"
      8 
      9 #include "base/command_line.h"
     10 #include "base/debug/debug_on_start_win.h"
     11 #include "base/process/kill.h"
     12 #include "base/threading/thread.h"
     13 #include "base/time/time.h"
     14 #include "ipc/ipc_descriptors.h"
     15 #include "ipc/ipc_switches.h"
     16 
     17 #if defined(OS_POSIX)
     18 #include "base/posix/global_descriptors.h"
     19 #endif
     20 
     21 // static
     22 std::string IPCTestBase::GetChannelName(const std::string& test_client_name) {
     23   DCHECK(!test_client_name.empty());
     24   return test_client_name + "__Channel";
     25 }
     26 
     27 IPCTestBase::IPCTestBase()
     28     : client_process_(base::kNullProcessHandle) {
     29 }
     30 
     31 IPCTestBase::~IPCTestBase() {
     32 }
     33 
     34 void IPCTestBase::SetUp() {
     35   MultiProcessTest::SetUp();
     36 
     37   // Construct a fresh IO Message loop for the duration of each test.
     38   DCHECK(!message_loop_.get());
     39   message_loop_.reset(new base::MessageLoopForIO());
     40 }
     41 
     42 void IPCTestBase::TearDown() {
     43   DCHECK(message_loop_.get());
     44   message_loop_.reset();
     45   MultiProcessTest::TearDown();
     46 }
     47 
     48 void IPCTestBase::Init(const std::string& test_client_name) {
     49   DCHECK(!test_client_name.empty());
     50   DCHECK(test_client_name_.empty());
     51   test_client_name_ = test_client_name;
     52 }
     53 
     54 void IPCTestBase::CreateChannel(IPC::Listener* listener) {
     55   return CreateChannelFromChannelHandle(GetChannelName(test_client_name_),
     56                                         listener);
     57 }
     58 
     59 bool IPCTestBase::ConnectChannel() {
     60   CHECK(channel_.get());
     61   return channel_->Connect();
     62 }
     63 
     64 void IPCTestBase::DestroyChannel() {
     65   DCHECK(channel_.get());
     66   channel_.reset();
     67 }
     68 
     69 void IPCTestBase::CreateChannelFromChannelHandle(
     70     const IPC::ChannelHandle& channel_handle,
     71     IPC::Listener* listener) {
     72   CHECK(!channel_.get());
     73   CHECK(!channel_proxy_.get());
     74   channel_.reset(new IPC::Channel(channel_handle,
     75                                   IPC::Channel::MODE_SERVER,
     76                                   listener));
     77 }
     78 
     79 void IPCTestBase::CreateChannelProxy(
     80     IPC::Listener* listener,
     81     base::SingleThreadTaskRunner* ipc_task_runner) {
     82   CHECK(!channel_.get());
     83   CHECK(!channel_proxy_.get());
     84   channel_proxy_.reset(new IPC::ChannelProxy(GetChannelName(test_client_name_),
     85                                              IPC::Channel::MODE_SERVER,
     86                                              listener,
     87                                              ipc_task_runner));
     88 }
     89 
     90 void IPCTestBase::DestroyChannelProxy() {
     91   CHECK(channel_proxy_.get());
     92   channel_proxy_.reset();
     93 }
     94 
     95 bool IPCTestBase::StartClient() {
     96   DCHECK(client_process_ == base::kNullProcessHandle);
     97 
     98   std::string test_main = test_client_name_ + "TestClientMain";
     99   bool debug_on_start =
    100       CommandLine::ForCurrentProcess()->HasSwitch(switches::kDebugChildren);
    101 
    102 #if defined(OS_WIN)
    103   client_process_ = MultiProcessTest::SpawnChild(test_main, debug_on_start);
    104 #elif defined(OS_POSIX)
    105   base::FileHandleMappingVector fds_to_map;
    106   const int ipcfd = channel_.get() ? channel_->GetClientFileDescriptor() :
    107                                      channel_proxy_->GetClientFileDescriptor();
    108   if (ipcfd > -1)
    109     fds_to_map.push_back(std::pair<int, int>(ipcfd,
    110         kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
    111 
    112   client_process_ = MultiProcessTest::SpawnChild(test_main,
    113                                                  fds_to_map,
    114                                                  debug_on_start);
    115 #endif
    116 
    117   return client_process_ != base::kNullProcessHandle;
    118 }
    119 
    120 bool IPCTestBase::WaitForClientShutdown() {
    121   DCHECK(client_process_ != base::kNullProcessHandle);
    122 
    123   bool rv = base::WaitForSingleProcess(client_process_,
    124                                        base::TimeDelta::FromSeconds(5));
    125   base::CloseProcessHandle(client_process_);
    126   client_process_ = base::kNullProcessHandle;
    127   return rv;
    128 }
    129