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::TearDown() {
     33   message_loop_.reset();
     34   MultiProcessTest::TearDown();
     35 }
     36 
     37 void IPCTestBase::Init(const std::string& test_client_name) {
     38   InitWithCustomMessageLoop(
     39       test_client_name,
     40       scoped_ptr<base::MessageLoop>(new base::MessageLoopForIO()));
     41 }
     42 
     43 void IPCTestBase::InitWithCustomMessageLoop(
     44     const std::string& test_client_name,
     45     scoped_ptr<base::MessageLoop> message_loop) {
     46   DCHECK(!test_client_name.empty());
     47   DCHECK(test_client_name_.empty());
     48   DCHECK(!message_loop_);
     49 
     50   test_client_name_ = test_client_name;
     51   message_loop_ = message_loop.Pass();
     52 }
     53 
     54 void IPCTestBase::CreateChannel(IPC::Listener* listener) {
     55   CreateChannelFromChannelHandle(GetTestChannelHandle(), listener);
     56 }
     57 
     58 bool IPCTestBase::ConnectChannel() {
     59   CHECK(channel_.get());
     60   return channel_->Connect();
     61 }
     62 
     63 scoped_ptr<IPC::Channel> IPCTestBase::ReleaseChannel() {
     64   return channel_.Pass();
     65 }
     66 
     67 void IPCTestBase::SetChannel(scoped_ptr<IPC::Channel> channel) {
     68   channel_ = channel.Pass();
     69 }
     70 
     71 
     72 void IPCTestBase::DestroyChannel() {
     73   DCHECK(channel_.get());
     74   channel_.reset();
     75 }
     76 
     77 void IPCTestBase::CreateChannelFromChannelHandle(
     78     const IPC::ChannelHandle& channel_handle,
     79     IPC::Listener* listener) {
     80   CHECK(!channel_.get());
     81   CHECK(!channel_proxy_.get());
     82   channel_ = CreateChannelFactory(
     83       channel_handle, task_runner().get())->BuildChannel(listener);
     84 }
     85 
     86 void IPCTestBase::CreateChannelProxy(
     87     IPC::Listener* listener,
     88     const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
     89   CHECK(!channel_.get());
     90   CHECK(!channel_proxy_.get());
     91   channel_proxy_ = IPC::ChannelProxy::Create(
     92       CreateChannelFactory(GetTestChannelHandle(), ipc_task_runner.get()),
     93       listener,
     94       ipc_task_runner);
     95 }
     96 
     97 void IPCTestBase::DestroyChannelProxy() {
     98   CHECK(channel_proxy_.get());
     99   channel_proxy_.reset();
    100 }
    101 
    102 std::string IPCTestBase::GetTestMainName() const {
    103   return test_client_name_ + "TestClientMain";
    104 }
    105 
    106 bool IPCTestBase::DidStartClient() {
    107   DCHECK_NE(base::kNullProcessHandle, client_process_);
    108   return client_process_ != base::kNullProcessHandle;
    109 }
    110 
    111 #if defined(OS_POSIX)
    112 
    113 bool IPCTestBase::StartClient() {
    114   return StartClientWithFD(channel_
    115                                ? channel_->GetClientFileDescriptor()
    116                                : channel_proxy_->GetClientFileDescriptor());
    117 }
    118 
    119 bool IPCTestBase::StartClientWithFD(int ipcfd) {
    120   DCHECK_EQ(client_process_, base::kNullProcessHandle);
    121 
    122   base::FileHandleMappingVector fds_to_map;
    123   if (ipcfd > -1)
    124     fds_to_map.push_back(std::pair<int, int>(ipcfd,
    125         kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
    126   base::LaunchOptions options;
    127   options.fds_to_remap = &fds_to_map;
    128   client_process_ = SpawnChildWithOptions(GetTestMainName(), options);
    129 
    130   return DidStartClient();
    131 }
    132 
    133 #elif defined(OS_WIN)
    134 
    135 bool IPCTestBase::StartClient() {
    136   DCHECK_EQ(client_process_, base::kNullProcessHandle);
    137   client_process_ = SpawnChild(GetTestMainName());
    138   return DidStartClient();
    139 }
    140 
    141 #endif
    142 
    143 bool IPCTestBase::WaitForClientShutdown() {
    144   DCHECK(client_process_ != base::kNullProcessHandle);
    145 
    146   bool rv = base::WaitForSingleProcess(client_process_,
    147                                        base::TimeDelta::FromSeconds(5));
    148   base::CloseProcessHandle(client_process_);
    149   client_process_ = base::kNullProcessHandle;
    150   return rv;
    151 }
    152 
    153 IPC::ChannelHandle IPCTestBase::GetTestChannelHandle() {
    154   return GetChannelName(test_client_name_);
    155 }
    156 
    157 scoped_refptr<base::TaskRunner> IPCTestBase::task_runner() {
    158   return message_loop_->message_loop_proxy();
    159 }
    160 
    161 scoped_ptr<IPC::ChannelFactory> IPCTestBase::CreateChannelFactory(
    162     const IPC::ChannelHandle& handle,
    163     base::TaskRunner* runner) {
    164   return IPC::ChannelFactory::Create(handle, IPC::Channel::MODE_SERVER);
    165 }
    166