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