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/process/kill.h"
     11 #include "base/threading/thread.h"
     12 #include "base/time/time.h"
     13 #include "ipc/ipc_descriptors.h"
     14 
     15 #if defined(OS_POSIX)
     16 #include "base/posix/global_descriptors.h"
     17 #endif
     18 
     19 // static
     20 std::string IPCTestBase::GetChannelName(const std::string& test_client_name) {
     21   DCHECK(!test_client_name.empty());
     22   return test_client_name + "__Channel";
     23 }
     24 
     25 IPCTestBase::IPCTestBase()
     26     : client_process_(base::kNullProcessHandle) {
     27 }
     28 
     29 IPCTestBase::~IPCTestBase() {
     30 }
     31 
     32 void IPCTestBase::SetUp() {
     33   MultiProcessTest::SetUp();
     34 
     35   // Construct a fresh IO Message loop for the duration of each test.
     36   DCHECK(!message_loop_.get());
     37   message_loop_.reset(new base::MessageLoopForIO());
     38 }
     39 
     40 void IPCTestBase::TearDown() {
     41   DCHECK(message_loop_.get());
     42   message_loop_.reset();
     43   MultiProcessTest::TearDown();
     44 }
     45 
     46 void IPCTestBase::Init(const std::string& test_client_name) {
     47   DCHECK(!test_client_name.empty());
     48   DCHECK(test_client_name_.empty());
     49   test_client_name_ = test_client_name;
     50 }
     51 
     52 void IPCTestBase::CreateChannel(IPC::Listener* listener) {
     53   return CreateChannelFromChannelHandle(GetChannelName(test_client_name_),
     54                                         listener);
     55 }
     56 
     57 bool IPCTestBase::ConnectChannel() {
     58   CHECK(channel_.get());
     59   return channel_->Connect();
     60 }
     61 
     62 void IPCTestBase::DestroyChannel() {
     63   DCHECK(channel_.get());
     64   channel_.reset();
     65 }
     66 
     67 void IPCTestBase::CreateChannelFromChannelHandle(
     68     const IPC::ChannelHandle& channel_handle,
     69     IPC::Listener* listener) {
     70   CHECK(!channel_.get());
     71   CHECK(!channel_proxy_.get());
     72   channel_ = IPC::Channel::CreateServer(channel_handle, listener);
     73 }
     74 
     75 void IPCTestBase::CreateChannelProxy(
     76     IPC::Listener* listener,
     77     base::SingleThreadTaskRunner* ipc_task_runner) {
     78   CHECK(!channel_.get());
     79   CHECK(!channel_proxy_.get());
     80   channel_proxy_ = IPC::ChannelProxy::Create(GetChannelName(test_client_name_),
     81                                              IPC::Channel::MODE_SERVER,
     82                                              listener,
     83                                              ipc_task_runner);
     84 }
     85 
     86 void IPCTestBase::DestroyChannelProxy() {
     87   CHECK(channel_proxy_.get());
     88   channel_proxy_.reset();
     89 }
     90 
     91 bool IPCTestBase::StartClient() {
     92   DCHECK(client_process_ == base::kNullProcessHandle);
     93 
     94   std::string test_main = test_client_name_ + "TestClientMain";
     95 
     96 #if defined(OS_WIN)
     97   client_process_ = SpawnChild(test_main);
     98 #elif defined(OS_POSIX)
     99   base::FileHandleMappingVector fds_to_map;
    100   const int ipcfd = channel_.get()
    101       ? channel_->GetClientFileDescriptor()
    102       : channel_proxy_->GetClientFileDescriptor();
    103   if (ipcfd > -1)
    104     fds_to_map.push_back(std::pair<int, int>(ipcfd,
    105         kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
    106   base::LaunchOptions options;
    107   options.fds_to_remap = &fds_to_map;
    108   client_process_ = SpawnChildWithOptions(test_main, options);
    109 #endif
    110 
    111   return client_process_ != base::kNullProcessHandle;
    112 }
    113 
    114 bool IPCTestBase::WaitForClientShutdown() {
    115   DCHECK(client_process_ != base::kNullProcessHandle);
    116 
    117   bool rv = base::WaitForSingleProcess(client_process_,
    118                                        base::TimeDelta::FromSeconds(5));
    119   base::CloseProcessHandle(client_process_);
    120   client_process_ = base::kNullProcessHandle;
    121   return rv;
    122 }
    123