12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "build/build_config.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_test_base.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
10a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/kill.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_descriptors.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_POSIX)
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/posix/global_descriptors.h"
1758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif
1858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string IPCTestBase::GetChannelName(const std::string& test_client_name) {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!test_client_name.empty());
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return test_client_name + "__Channel";
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IPCTestBase::IPCTestBase()
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : client_process_(base::kNullProcessHandle) {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IPCTestBase::~IPCTestBase() {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IPCTestBase::SetUp() {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MultiProcessTest::SetUp();
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Construct a fresh IO Message loop for the duration of each test.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!message_loop_.get());
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  message_loop_.reset(new base::MessageLoopForIO());
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IPCTestBase::TearDown() {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(message_loop_.get());
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.reset();
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MultiProcessTest::TearDown();
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IPCTestBase::Init(const std::string& test_client_name) {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!test_client_name.empty());
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(test_client_name_.empty());
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  test_client_name_ = test_client_name;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IPCTestBase::CreateChannel(IPC::Listener* listener) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return CreateChannelFromChannelHandle(GetChannelName(test_client_name_),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        listener);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IPCTestBase::ConnectChannel() {
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(channel_.get());
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return channel_->Connect();
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IPCTestBase::DestroyChannel() {
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(channel_.get());
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  channel_.reset();
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IPCTestBase::CreateChannelFromChannelHandle(
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const IPC::ChannelHandle& channel_handle,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC::Listener* listener) {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(!channel_.get());
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(!channel_proxy_.get());
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  channel_ = IPC::Channel::CreateServer(channel_handle, listener);
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IPCTestBase::CreateChannelProxy(
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IPC::Listener* listener,
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::SingleThreadTaskRunner* ipc_task_runner) {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(!channel_.get());
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(!channel_proxy_.get());
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  channel_proxy_ = IPC::ChannelProxy::Create(GetChannelName(test_client_name_),
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             IPC::Channel::MODE_SERVER,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             listener,
8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                             ipc_task_runner);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void IPCTestBase::DestroyChannelProxy() {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(channel_proxy_.get());
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  channel_proxy_.reset();
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IPCTestBase::StartClient() {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(client_process_ == base::kNullProcessHandle);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string test_main = test_client_name_ + "TestClientMain";
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN)
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  client_process_ = SpawnChild(test_main);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_POSIX)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FileHandleMappingVector fds_to_map;
10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const int ipcfd = channel_.get()
10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ? channel_->GetClientFileDescriptor()
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      : channel_proxy_->GetClientFileDescriptor();
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ipcfd > -1)
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    fds_to_map.push_back(std::pair<int, int>(ipcfd,
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::LaunchOptions options;
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  options.fds_to_remap = &fds_to_map;
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  client_process_ = SpawnChildWithOptions(test_main, options);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return client_process_ != base::kNullProcessHandle;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IPCTestBase::WaitForClientShutdown() {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(client_process_ != base::kNullProcessHandle);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool rv = base::WaitForSingleProcess(client_process_,
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       base::TimeDelta::FromSeconds(5));
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::CloseProcessHandle(client_process_);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_process_ = base::kNullProcessHandle;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return rv;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
123