// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "test/multiprocess_exec.h"

#include <sys/types.h>

#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "gtest/gtest.h"
#include "util/win/command_line.h"

namespace crashpad {
namespace test {

namespace internal {

struct MultiprocessInfo {
  MultiprocessInfo() {}
  ScopedFileHANDLE pipe_c2p_read;
  ScopedFileHANDLE pipe_c2p_write;
  ScopedFileHANDLE pipe_p2c_read;
  ScopedFileHANDLE pipe_p2c_write;
  PROCESS_INFORMATION process_info;
};

}  // namespace internal

Multiprocess::Multiprocess()
    : info_(nullptr),
      code_(EXIT_SUCCESS),
      reason_(kTerminationNormal) {
}

void Multiprocess::Run() {
  // Set up and spawn the child process.
  ASSERT_NO_FATAL_FAILURE(PreFork());
  RunChild();

  // And then run the parent actions in this process.
  RunParent();

  // Reap the child.
  WaitForSingleObject(info_->process_info.hProcess, INFINITE);
  CloseHandle(info_->process_info.hThread);
  CloseHandle(info_->process_info.hProcess);
}

void Multiprocess::SetExpectedChildTermination(TerminationReason reason,
                                               ReturnCodeType code) {
  EXPECT_EQ(info_, nullptr)
      << "SetExpectedChildTermination() must be called before Run()";
  reason_ = reason;
  code_ = code;
}

Multiprocess::~Multiprocess() {
  delete info_;
}

FileHandle Multiprocess::ReadPipeHandle() const {
  // This is the parent case, it's stdin in the child.
  return info_->pipe_c2p_read.get();
}

FileHandle Multiprocess::WritePipeHandle() const {
  // This is the parent case, it's stdout in the child.
  return info_->pipe_p2c_write.get();
}

void Multiprocess::CloseReadPipe() {
  info_->pipe_c2p_read.reset();
}

void Multiprocess::CloseWritePipe() {
  info_->pipe_p2c_write.reset();
}

void Multiprocess::RunParent() {
  MultiprocessParent();

  info_->pipe_c2p_read.reset();
  info_->pipe_p2c_write.reset();
}

void Multiprocess::RunChild() {
  MultiprocessChild();

  info_->pipe_c2p_write.reset();
  info_->pipe_p2c_read.reset();
}

MultiprocessExec::MultiprocessExec()
    : Multiprocess(), command_(), arguments_(), command_line_() {
}

void MultiprocessExec::SetChildCommand(
    const base::FilePath& command,
    const std::vector<std::string>* arguments) {
  command_ = command;
  if (arguments) {
    arguments_ = *arguments;
  } else {
    arguments_.clear();
  }
}

MultiprocessExec::~MultiprocessExec() {
}

void MultiprocessExec::PreFork() {
  ASSERT_FALSE(command_.empty());

  command_line_.clear();
  AppendCommandLineArgument(command_.value(), &command_line_);
  for (size_t i = 0; i < arguments_.size(); ++i) {
    AppendCommandLineArgument(base::UTF8ToUTF16(arguments_[i]), &command_line_);
  }

  // Make pipes for child-to-parent and parent-to-child communication. Mark them
  // as inheritable via the SECURITY_ATTRIBUTES, but use SetHandleInformation to
  // ensure that the parent sides are not inherited.
  ASSERT_EQ(info(), nullptr);
  set_info(new internal::MultiprocessInfo());

  SECURITY_ATTRIBUTES security_attributes = {0};
  security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
  security_attributes.bInheritHandle = TRUE;

  HANDLE c2p_read, c2p_write;
  PCHECK(CreatePipe(&c2p_read, &c2p_write, &security_attributes, 0));
  PCHECK(SetHandleInformation(c2p_read, HANDLE_FLAG_INHERIT, 0));
  info()->pipe_c2p_read.reset(c2p_read);
  info()->pipe_c2p_write.reset(c2p_write);

  HANDLE p2c_read, p2c_write;
  PCHECK(CreatePipe(&p2c_read, &p2c_write, &security_attributes, 0));
  PCHECK(SetHandleInformation(p2c_write, HANDLE_FLAG_INHERIT, 0));
  info()->pipe_p2c_read.reset(p2c_read);
  info()->pipe_p2c_write.reset(p2c_write);
}

void MultiprocessExec::MultiprocessChild() {
  STARTUPINFO startup_info = {0};
  startup_info.cb = sizeof(startup_info);
  startup_info.hStdInput = info()->pipe_p2c_read.get();
  startup_info.hStdOutput = info()->pipe_c2p_write.get();
  startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
  startup_info.dwFlags = STARTF_USESTDHANDLES;
  PCHECK(CreateProcess(command_.value().c_str(),
                       &command_line_[0],  // This cannot be constant, per MSDN.
                       nullptr,
                       nullptr,
                       TRUE,
                       0,
                       nullptr,
                       nullptr,
                       &startup_info,
                       &info()->process_info));
}

ProcessType MultiprocessExec::ChildProcess() {
  return info()->process_info.hProcess;
}

}  // namespace test
}  // namespace crashpad
