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