// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ipc/ipc_test_base.h"

#include <utility>

#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/process/kill.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "ipc/ipc_channel_mojo.h"
#include "ipc/ipc_descriptors.h"

#if defined(OS_POSIX)
#include "base/posix/global_descriptors.h"
#endif

// static
std::string IPCTestBase::GetChannelName(const std::string& test_client_name) {
  DCHECK(!test_client_name.empty());
  return test_client_name + "__Channel";
}

IPCTestBase::IPCTestBase() {
}

IPCTestBase::~IPCTestBase() {
}

void IPCTestBase::TearDown() {
  message_loop_.reset();
  MultiProcessTest::TearDown();
}

void IPCTestBase::Init(const std::string& test_client_name) {
  InitWithCustomMessageLoop(test_client_name,
                            base::MakeUnique<base::MessageLoopForIO>());
}

void IPCTestBase::InitWithCustomMessageLoop(
    const std::string& test_client_name,
    std::unique_ptr<base::MessageLoop> message_loop) {
  DCHECK(!test_client_name.empty());
  DCHECK(test_client_name_.empty());
  DCHECK(!message_loop_);

  test_client_name_ = test_client_name;
  message_loop_ = std::move(message_loop);
}

void IPCTestBase::CreateChannel(IPC::Listener* listener) {
  CreateChannelFromChannelHandle(GetTestChannelHandle(), listener);
}

bool IPCTestBase::ConnectChannel() {
  CHECK(channel_.get());
  return channel_->Connect();
}

std::unique_ptr<IPC::Channel> IPCTestBase::ReleaseChannel() {
  return std::move(channel_);
}

void IPCTestBase::SetChannel(std::unique_ptr<IPC::Channel> channel) {
  channel_ = std::move(channel);
}


void IPCTestBase::DestroyChannel() {
  DCHECK(channel_.get());
  channel_.reset();
}

void IPCTestBase::CreateChannelFromChannelHandle(
    const IPC::ChannelHandle& channel_handle,
    IPC::Listener* listener) {
  CHECK(!channel_.get());
  CHECK(!channel_proxy_.get());
  channel_ = CreateChannelFactory(
      channel_handle, task_runner().get())->BuildChannel(listener);
}

void IPCTestBase::CreateChannelProxy(
    IPC::Listener* listener,
    const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) {
  CHECK(!channel_.get());
  CHECK(!channel_proxy_.get());
  channel_proxy_ = IPC::ChannelProxy::Create(
      CreateChannelFactory(GetTestChannelHandle(), ipc_task_runner.get()),
      listener, ipc_task_runner);
}

void IPCTestBase::DestroyChannelProxy() {
  CHECK(channel_proxy_.get());
  channel_proxy_.reset();
}

std::string IPCTestBase::GetTestMainName() const {
  return test_client_name_ + "TestClientMain";
}

bool IPCTestBase::DidStartClient() {
  DCHECK(client_process_.IsValid());
  return client_process_.IsValid();
}

#if defined(OS_POSIX)

bool IPCTestBase::StartClient() {
  return StartClientWithFD(channel_
                               ? channel_->GetClientFileDescriptor()
                               : channel_proxy_->GetClientFileDescriptor());
}

bool IPCTestBase::StartClientWithFD(int ipcfd) {
  DCHECK(!client_process_.IsValid());

  base::FileHandleMappingVector fds_to_map;
  if (ipcfd > -1)
    fds_to_map.push_back(std::pair<int, int>(ipcfd,
        kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
  base::LaunchOptions options;
  options.fds_to_remap = &fds_to_map;
  client_process_ = SpawnChildWithOptions(GetTestMainName(), options);

  return DidStartClient();
}

#elif defined(OS_WIN)

bool IPCTestBase::StartClient() {
  DCHECK(!client_process_.IsValid());
  client_process_ = SpawnChild(GetTestMainName());
  return DidStartClient();
}

#endif

bool IPCTestBase::WaitForClientShutdown() {
  DCHECK(client_process_.IsValid());

  int exit_code;
#if defined(OS_ANDROID)
  bool rv = AndroidWaitForChildExitWithTimeout(
      client_process_, base::TimeDelta::FromSeconds(5), &exit_code);
#else
  bool rv = client_process_.WaitForExitWithTimeout(
      base::TimeDelta::FromSeconds(5), &exit_code);
#endif  // defined(OS_ANDROID)
  client_process_.Close();
  return rv;
}

IPC::ChannelHandle IPCTestBase::GetTestChannelHandle() {
  return GetChannelName(test_client_name_);
}

scoped_refptr<base::SingleThreadTaskRunner> IPCTestBase::task_runner() {
  return message_loop_->task_runner();
}

std::unique_ptr<IPC::ChannelFactory> IPCTestBase::CreateChannelFactory(
    const IPC::ChannelHandle& handle,
    base::SingleThreadTaskRunner* runner) {
  return IPC::ChannelFactory::Create(handle, IPC::Channel::MODE_SERVER, runner);
}
IPCChannelMojoTestBase::IPCChannelMojoTestBase() = default;
IPCChannelMojoTestBase::~IPCChannelMojoTestBase() = default;

void IPCChannelMojoTestBase::Init(const std::string& test_client_name) {
  handle_ = helper_.StartChild(test_client_name);
}

bool IPCChannelMojoTestBase::WaitForClientShutdown() {
  return helper_.WaitForChildTestShutdown();
}

void IPCChannelMojoTestBase::TearDown() {
  base::RunLoop().RunUntilIdle();
}

void IPCChannelMojoTestBase::CreateChannel(IPC::Listener* listener) {
  channel_ =
      IPC::ChannelMojo::Create(TakeHandle(), IPC::Channel::MODE_SERVER,
                               listener, base::ThreadTaskRunnerHandle::Get());
}

bool IPCChannelMojoTestBase::ConnectChannel() {
  return channel_->Connect();
}

void IPCChannelMojoTestBase::DestroyChannel() {
  channel_.reset();
}

mojo::ScopedMessagePipeHandle IPCChannelMojoTestBase::TakeHandle() {
  return std::move(handle_);
}

IpcChannelMojoTestClient::IpcChannelMojoTestClient() = default;

IpcChannelMojoTestClient::~IpcChannelMojoTestClient() = default;

void IpcChannelMojoTestClient::Init(mojo::ScopedMessagePipeHandle handle) {
  handle_ = std::move(handle);
}

void IpcChannelMojoTestClient::Connect(IPC::Listener* listener) {
  channel_ =
      IPC::ChannelMojo::Create(std::move(handle_), IPC::Channel::MODE_CLIENT,
                               listener, base::ThreadTaskRunnerHandle::Get());
  CHECK(channel_->Connect());
}

void IpcChannelMojoTestClient::Close() {
  channel_->Close();

  base::RunLoop run_loop;
  base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
                                                run_loop.QuitClosure());
  run_loop.Run();
}
