// Copyright 2018 The Fuchsia 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 <cstdio>
#include <cstdlib>
#include <limits>
#include <string>
#include <vector>

#include <src/lib/fxl/log_settings_command_line.h>
#include <src/lib/fxl/logging.h>
#include <src/lib/fxl/strings/string_printf.h>
#include <lib/sys/cpp/service_directory.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>

#include "garnet/lib/debugger_utils/jobs.h"
#include "garnet/lib/debugger_utils/sysinfo.h"
#include "garnet/lib/debugger_utils/util.h"

#include "gtest/gtest.h"

#include "test_server.h"

namespace inferior_control {

TestServer::TestServer()
    : Server(debugger_utils::GetRootJob(), debugger_utils::GetDefaultJob(),
             sys::ServiceDirectory::CreateFromNamespace()) {
}

void TestServer::SetUp() {
  ASSERT_TRUE(exception_port_.Run());
  exception_port_started_ = true;
}

void TestServer::TearDown() {
  // Before we close the exception port, make sure we've detached.
  Process* inferior = current_process();
  if (inferior && inferior->IsAttached()) {
    inferior->Kill();
    inferior->Detach();
  }

  if (exception_port_started_) {
    // Tell the exception port to quit and wait for it to finish.
    exception_port_.Quit();
    exception_port_started_ = false;
  }

  EXPECT_TRUE(run_status_);
}

bool TestServer::Run() {
  // Start the main loop.
  zx_status_t status = message_loop_.Run();

  FXL_LOG(INFO) << "Main loop exited, status "
                << debugger_utils::ZxErrorString(status);

  // |run_status_| is checked by TearDown().
  return true;
}

bool TestServer::SetupInferior(const std::vector<std::string>& argv,
                               zx::channel channel) {
  FXL_LOG(INFO) << "Initializing program: " << argv[0];

  auto inferior = new Process(this, this);

  // We take over ownership of |inferior| here.
  set_current_process(inferior);

  // Transfer our log settings to the inferior.
  std::vector<std::string> inferior_argv{argv};
  for (auto arg : fxl::LogSettingsToArgv(fxl::GetLogSettings())) {
    inferior_argv.push_back(arg);
  }

  std::unique_ptr<process::ProcessBuilder> builder;
  if (!CreateProcessViaBuilder(argv[0], inferior_argv, &builder)) {
    FXL_LOG(ERROR) << "Unable to create process builder";
    return false;
  }

  builder->CloneAll();

  if (channel) {
    builder->AddHandle(PA_HND(PA_USER0, 0), std::move(channel));
  }

  if (!inferior->InitializeFromBuilder(std::move(builder))) {
    FXL_LOG(ERROR) << "Unable to initialize inferior";
    return false;
  }

  return true;
}

bool TestServer::RunHelperProgram() {
  Process* inferior = current_process();

  FXL_LOG(INFO) << "Starting program: " << inferior->GetName();

  FXL_DCHECK(!inferior->IsLive());
  if (!inferior->Start()) {
    FXL_LOG(ERROR) << "failed to start process";
    return false;
  }
  FXL_DCHECK(inferior->IsLive());

  return true;
}

// This method is intended to be called at the end of tests.
// There are several things we check for successful exit, and it's easier
// to have them all in one place. Note that we use gtest macros instead of
// FXL_DCHECK because these all verify test conditions.
bool TestServer::TestSuccessfulExit() {
  auto inferior = current_process();
  if (inferior == nullptr) {
    FXL_LOG(ERROR) << "inferior == nullptr";
    return false;
  }
  if (inferior->IsAttached()) {
    // The program should have terminated some how, in which case we would
    // have detached. So it's likely the program is still running.
    FXL_LOG(ERROR) << "inferior still attached";
    return false;
  }
  if (inferior->IsLive()) {
    FXL_LOG(ERROR) << "inferior still live";
    return false;
  }
  if (!inferior->return_code_is_set() || inferior->return_code() != 0) {
    FXL_LOG(ERROR) << "inferior didn't cleanly exit";
    return false;
  }
  return true;
}

// This method is intended to be called at the end of tests.
// There are several things we check for successful exit, and it's easier
// to have them all in one place. Note that we use gtest macros instead of
// FXL_DCHECK because these all verify test conditions.
bool TestServer::TestFailureExit() {
  auto inferior = current_process();
  if (inferior == nullptr) {
    FXL_LOG(ERROR) << "inferior == nullptr";
    return false;
  }
  if (inferior->IsAttached()) {
    // The program should have terminated some how, in which case we would
    // have detached. So it's likely the program is still running.
    FXL_LOG(ERROR) << "inferior still attached";
    return false;
  }
  if (inferior->IsLive()) {
    FXL_LOG(ERROR) << "inferior still live";
    return false;
  }
  if (inferior->return_code_is_set() && inferior->return_code() == 0) {
    FXL_LOG(ERROR) << "inferior successfully exited";
    return false;
  }
  return true;
}

void TestServer::OnThreadStarting(Process* process, Thread* thread,
                                  zx_handle_t eport,
                                  const zx_exception_context_t& context) {
  FXL_DCHECK(process);
  FXL_DCHECK(thread);

  switch (process->state()) {
    case Process::State::kStarting:
    case Process::State::kRunning:
      break;
    default:
      FXL_DCHECK(false);
  }

  thread->ResumeFromException(eport);
}

void TestServer::OnThreadExiting(Process* process, Thread* thread,
                                 zx_handle_t eport,
                                 const zx_exception_context_t& context) {
  FXL_DCHECK(process);
  FXL_DCHECK(thread);

  // We still have to "resume" the thread so that the o/s will complete the
  // termination of the thread.
  thread->ResumeForExit(eport);
}

void TestServer::OnProcessTermination(Process* process) {
  FXL_DCHECK(process);

  FXL_LOG(INFO) << fxl::StringPrintf("Process %s is gone, rc %d",
                                     process->GetName().c_str(),
                                     process->return_code());

  // Process is gone, exit main loop.
  PostQuitMessageLoop(true);
}

void TestServer::OnArchitecturalException(
    Process* process, Thread* thread, zx_handle_t eport, zx_excp_type_t type,
    const zx_exception_context_t& context) {
  FXL_DCHECK(process);
  FXL_DCHECK(thread);

  PostQuitMessageLoop(true);
}

void TestServer::OnSyntheticException(
    Process* process, Thread* thread, zx_handle_t eport, zx_excp_type_t type,
    const zx_exception_context_t& context) {
  FXL_DCHECK(process);
  FXL_DCHECK(thread);

  PostQuitMessageLoop(true);
}

}  // namespace inferior_control
