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 20std::string IPCTestBase::GetChannelName(const std::string& test_client_name) { 21 DCHECK(!test_client_name.empty()); 22 return test_client_name + "__Channel"; 23} 24 25IPCTestBase::IPCTestBase() 26 : client_process_(base::kNullProcessHandle) { 27} 28 29IPCTestBase::~IPCTestBase() { 30} 31 32void IPCTestBase::TearDown() { 33 message_loop_.reset(); 34 MultiProcessTest::TearDown(); 35} 36 37void IPCTestBase::Init(const std::string& test_client_name) { 38 InitWithCustomMessageLoop( 39 test_client_name, 40 scoped_ptr<base::MessageLoop>(new base::MessageLoopForIO())); 41} 42 43void 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 54void IPCTestBase::CreateChannel(IPC::Listener* listener) { 55 CreateChannelFromChannelHandle(GetTestChannelHandle(), listener); 56} 57 58bool IPCTestBase::ConnectChannel() { 59 CHECK(channel_.get()); 60 return channel_->Connect(); 61} 62 63scoped_ptr<IPC::Channel> IPCTestBase::ReleaseChannel() { 64 return channel_.Pass(); 65} 66 67void IPCTestBase::SetChannel(scoped_ptr<IPC::Channel> channel) { 68 channel_ = channel.Pass(); 69} 70 71 72void IPCTestBase::DestroyChannel() { 73 DCHECK(channel_.get()); 74 channel_.reset(); 75} 76 77void 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 86void 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 97void IPCTestBase::DestroyChannelProxy() { 98 CHECK(channel_proxy_.get()); 99 channel_proxy_.reset(); 100} 101 102std::string IPCTestBase::GetTestMainName() const { 103 return test_client_name_ + "TestClientMain"; 104} 105 106bool IPCTestBase::DidStartClient() { 107 DCHECK_NE(base::kNullProcessHandle, client_process_); 108 return client_process_ != base::kNullProcessHandle; 109} 110 111#if defined(OS_POSIX) 112 113bool IPCTestBase::StartClient() { 114 return StartClientWithFD(channel_ 115 ? channel_->GetClientFileDescriptor() 116 : channel_proxy_->GetClientFileDescriptor()); 117} 118 119bool 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 135bool IPCTestBase::StartClient() { 136 DCHECK_EQ(client_process_, base::kNullProcessHandle); 137 client_process_ = SpawnChild(GetTestMainName()); 138 return DidStartClient(); 139} 140 141#endif 142 143bool 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 153IPC::ChannelHandle IPCTestBase::GetTestChannelHandle() { 154 return GetChannelName(test_client_name_); 155} 156 157scoped_refptr<base::TaskRunner> IPCTestBase::task_runner() { 158 return message_loop_->message_loop_proxy(); 159} 160 161scoped_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