// 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 "test_server.h"

#include <array>
#include <cinttypes>
#include <cstdio>
#include <cstdlib>
#include <limits>
#include <string>
#include <vector>

#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 "lib/component/cpp/environment_services_helper.h"
#include "lib/fxl/arraysize.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/strings/string_printf.h"

namespace inferior_control {

TestServer::TestServer()
    : Server(debugger_utils::GetRootJob(), debugger_utils::GetDefaultJob()),
      services_(component::GetEnvironmentServices()) {}

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

void TestServer::TearDown() {
  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.
  message_loop_.Run();

  FXL_LOG(INFO) << "Main loop exited";

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

bool TestServer::SetupInferior(const std::vector<std::string>& argv) {
  auto inferior = new Process(this, this, services_);
  inferior->set_argv(argv);
  // We take over ownership of |inferior| here.
  set_current_process(inferior);
  return true;
}

bool TestServer::RunHelperProgram(zx::channel channel) {
  Process* process = current_process();
  const debugger_utils::Argv& argv = process->argv();

  FXL_LOG(INFO) << "Starting program: " << argv[0];

  if (channel.is_valid()) {
    process->AddStartupHandle({
        .id = PA_HND(PA_USER0, 0),
        .handle = std::move(channel),
    });
  }

  if (!process->Initialize()) {
    FXL_LOG(ERROR) << "failed to set up inferior";
    return false;
  }

  FXL_DCHECK(!process->IsLive());
  if (!process->Start()) {
    FXL_LOG(ERROR) << "failed to start process";
    return false;
  }
  FXL_DCHECK(process->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()) {
    FXL_LOG(ERROR) << "inferior still attached";
    return false;
  }
  if (inferior->IsLive()) {
    FXL_LOG(ERROR) << "inferior still live";
    return false;
  }
  // We can't get the exit code from |inferior| as we've detached. Instead
  // we save it on process exit.
  if (!exit_code_set_ || exit_code_ != 0) {
    FXL_LOG(ERROR) << "inferior didn't cleanly exit";
    return false;
  }
  return true;
}

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

  PrintException(stdout, thread, ZX_EXCP_THREAD_STARTING, context);

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

  thread->Resume();
}

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

  PrintException(stdout, thread, ZX_EXCP_THREAD_EXITING, context);

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

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

  // Save the exit code for later testing.
  exit_code_ = process->ExitCode();
  exit_code_set_ = true;

  printf("Process %s is gone, rc %d\n", process->GetName().c_str(), exit_code_);

  // If the process is gone exit main loop.
  QuitMessageLoop(true);
}

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

  PrintException(stdout, thread, type, context);

  QuitMessageLoop(true);
}

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

  PrintException(stdout, thread, type, context);

  QuitMessageLoop(true);
}

}  // namespace inferior_control
