// Copyright 2019 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 "src/developer/debug/debug_agent/debug_agent.h"

#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>

#include <gtest/gtest.h>

#include "src/developer/debug/debug_agent/arch_provider_impl.h"
#include "src/developer/debug/debug_agent/local_stream_backend.h"
#include "src/developer/debug/debug_agent/mock_object_provider.h"
#include "src/developer/debug/debug_agent/mock_process.h"
#include "src/developer/debug/debug_agent/system_info.h"
#include "src/developer/debug/debug_agent/test_utils.h"
#include "src/developer/debug/ipc/agent_protocol.h"
#include "src/developer/debug/ipc/message_writer.h"
#include "src/developer/debug/shared/platform_message_loop.h"
#include "src/lib/fxl/strings/string_printf.h"

using namespace fuchsia::exception;

namespace debug_agent {
namespace {

// Setup -------------------------------------------------------------------------------------------

class DebugAgentMessageLoop : public debug_ipc::PlatformMessageLoop {
 public:
  DebugAgentMessageLoop() {
    std::string error_message;
    bool success = Init(&error_message);
    FX_CHECK(success) << error_message;
  }
  ~DebugAgentMessageLoop() { Cleanup(); }

  void StopWatching(int id) override {}

  zx_status_t WatchProcessExceptions(WatchProcessConfig config, WatchHandle* out) override {
    watches_.push_back(std::move(config));
    *out = WatchHandle(this, next_watch_id_++);
    return ZX_OK;
  }

  const std::vector<WatchProcessConfig> watches() const { return watches_; }

 private:
  int next_watch_id_ = 1;

  std::vector<WatchProcessConfig> watches_;
};

class DebugAgentStreamBackend : public LocalStreamBackend {
 public:
  void HandleAttach(debug_ipc::AttachReply attach_reply) override {
    attach_replies_.push_back(std::move(attach_reply));
  }

  void HandleNotifyProcessStarting(debug_ipc::NotifyProcessStarting notification) override {
    process_starts_.push_back(std::move(notification));
  }

  void HandleNotifyModules(debug_ipc::NotifyModules modules) override {
    modules_.push_back(std::move(modules));
  }

  const std::vector<debug_ipc::AttachReply>& attach_replies() const { return attach_replies_; }
  const std::vector<debug_ipc::NotifyProcessStarting>& process_starts() const {
    return process_starts_;
  }
  const std::vector<debug_ipc::NotifyModules> modules() const { return modules_; }

 private:
  std::vector<debug_ipc::AttachReply> attach_replies_;
  std::vector<debug_ipc::NotifyProcessStarting> process_starts_;
  std::vector<debug_ipc::NotifyModules> modules_;
};

class DebugAgentMockProcess : public MockProcess {
 public:
  DebugAgentMockProcess(DebugAgent* debug_agent, zx_koid_t koid, std::string name,
                        std::shared_ptr<ObjectProvider> object_provider,
                        std::shared_ptr<arch::ArchProvider> arch_provider)
      : MockProcess(debug_agent, koid, std::move(name), std::move(arch_provider),
                    std::move(object_provider)) {}

  ~DebugAgentMockProcess() = default;

  void SuspendAndSendModulesIfKnown() override {
    // Send the modules over to the ipc.
    debug_ipc::MessageWriter writer;
    debug_ipc::WriteNotifyModules(modules_to_send_, &writer);
    debug_agent()->stream()->Write(writer.MessageComplete());
  };

  void set_modules_to_send(debug_ipc::NotifyModules m) { modules_to_send_ = std::move(m); }

 private:
  debug_ipc::NotifyModules modules_to_send_;
};

class MockLimboProvider : public LimboProvider {
 public:
  MockLimboProvider() : LimboProvider(nullptr) {}

  const std::map<zx_koid_t, ProcessExceptionMetadata>& Limbo() const override { return limbo_; }
  const std::vector<zx_koid_t> release_calls() const { return release_calls_; }

  bool Valid() const override { return true; }

  zx_status_t RetrieveException(zx_koid_t process_koid,
                                fuchsia::exception::ProcessException* out) override {
    auto it = limbo_.find(process_koid);
    if (it == limbo_.end())
      return ZX_ERR_NOT_FOUND;

    *out = ToProcessException(it->second);

    limbo_.erase(it);
    return ZX_OK;
  }

  void AppendException(const MockProcessObject* process, const MockThreadObject* thread,
                       ExceptionType exception_type) {
    ExceptionInfo info = {};
    info.process_koid = process->koid;
    info.thread_koid = thread->koid;
    info.type = exception_type;

    ProcessExceptionMetadata metadata = {};
    metadata.set_info(std::move(info));
    metadata.set_process(process->GetHandle());
    metadata.set_thread(thread->GetHandle());

    limbo_[process->koid] = std::move(metadata);
  }

  void CallOnEnterLimbo() {
    FX_DCHECK(on_enter_limbo_);

    std::vector<ProcessExceptionMetadata> processes;
    processes.reserve(limbo_.size());
    for (const auto& [process_koid, metadata] : limbo_) {
      processes.push_back(CopyMetadata(metadata));
    }

    on_enter_limbo_(std::move(processes));
  }

  zx_status_t ReleaseProcess(zx_koid_t process_koid) override {
    release_calls_.push_back(process_koid);

    auto it = limbo_.find(process_koid);
    if (it == limbo_.end())
      return ZX_ERR_NOT_FOUND;

    limbo_.erase(it);
    return ZX_OK;
  }

 private:
  ProcessExceptionMetadata CopyMetadata(const ProcessExceptionMetadata& metadata) {
    ProcessExceptionMetadata exception = {};

    exception.set_info(metadata.info());
    exception.set_process(zx::process(metadata.info().process_koid));
    exception.set_thread(zx::thread(metadata.info().thread_koid));

    return exception;
  }

  ProcessException ToProcessException(const ProcessExceptionMetadata& metadata) {
    ProcessException exception = {};

    exception.set_info(metadata.info());
    exception.set_exception(zx::exception(metadata.info().thread_koid));
    exception.set_process(zx::process(metadata.info().process_koid));
    exception.set_thread(zx::thread(metadata.info().thread_koid));

    return exception;
  }

  std::map<zx_koid_t, ProcessExceptionMetadata> limbo_;
  std::vector<zx_koid_t> release_calls_;
};

class TestObjectProvider : public MockObjectProvider {
 public:
  zx_status_t Kill(zx_handle_t) override { return next_kill_status_; }

  void set_next_kill_status(zx_status_t status) { next_kill_status_ = status; }

 private:
  zx_status_t next_kill_status_ = ZX_OK;
};

std::pair<const MockProcessObject*, const MockThreadObject*> GetProcessThread(
    const MockObjectProvider& object_provider, const std::string& process_name,
    const std::string& thread_name) {
  const MockProcessObject* process = object_provider.ProcessByName(process_name);
  FX_DCHECK(process);
  const MockThreadObject* thread = process->GetThread(thread_name);
  FX_DCHECK(thread);

  return {process, thread};
}

struct TestContext {
  DebugAgentMessageLoop loop;
  DebugAgentStreamBackend stream_backend;

  std::shared_ptr<TestObjectProvider> object_provider;
  std::shared_ptr<MockLimboProvider> limbo_provider;
  std::shared_ptr<arch::ArchProvider> arch_provider;
};

SystemProviders ToSystemProviders(const TestContext& context) {
  SystemProviders providers;
  providers.arch_provider = context.arch_provider;
  providers.limbo_provider = context.limbo_provider;
  providers.object_provider = context.object_provider;

  return providers;
}

std::unique_ptr<TestContext> CreateTestContext() {
  auto context = std::make_unique<TestContext>();
  context->arch_provider = std::make_shared<ArchProviderImpl>();
  context->limbo_provider = std::make_shared<MockLimboProvider>();
  context->object_provider = std::make_unique<TestObjectProvider>();
  FillInMockObjectProvider(context->object_provider.get());
  return context;
}

}  // namespace

// Tests -------------------------------------------------------------------------------------------

class DebugAgentTests : public ::testing::Test {};

TEST_F(DebugAgentTests, OnGlobalStatus) {
  auto test_context = CreateTestContext();

  DebugAgent debug_agent(nullptr, ToSystemProviders(*test_context));
  debug_agent.Connect(&test_context->stream_backend.stream());
  RemoteAPI* remote_api = &debug_agent;

  debug_ipc::StatusRequest request = {};

  debug_ipc::StatusReply reply = {};
  remote_api->OnStatus(request, &reply);

  ASSERT_EQ(reply.processes.size(), 0u);

  constexpr uint64_t kProcessKoid1 = 0x1234;
  const std::string kProcessName1 = "process-1";
  constexpr uint64_t kProcess1ThreadKoid1 = 0x1;

  auto process1 =
      std::make_unique<MockProcess>(nullptr, kProcessKoid1, kProcessName1,
                                    test_context->arch_provider, test_context->object_provider);
  process1->AddThread(kProcess1ThreadKoid1);
  debug_agent.InjectProcessForTest(std::move(process1));

  reply = {};
  remote_api->OnStatus(request, &reply);

  ASSERT_EQ(reply.processes.size(), 1u);
  EXPECT_EQ(reply.processes[0].process_koid, kProcessKoid1);
  EXPECT_EQ(reply.processes[0].process_name, kProcessName1);
  ASSERT_EQ(reply.processes[0].threads.size(), 1u);
  EXPECT_EQ(reply.processes[0].threads[0].process_koid, kProcessKoid1);
  EXPECT_EQ(reply.processes[0].threads[0].thread_koid, kProcess1ThreadKoid1);

  constexpr uint64_t kProcessKoid2 = 0x5678;
  const std::string kProcessName2 = "process-2";
  constexpr uint64_t kProcess2ThreadKoid1 = 0x1;
  constexpr uint64_t kProcess2ThreadKoid2 = 0x2;

  auto process2 =
      std::make_unique<MockProcess>(nullptr, kProcessKoid2, kProcessName2,
                                    test_context->arch_provider, test_context->object_provider);
  process2->AddThread(kProcess2ThreadKoid1);
  process2->AddThread(kProcess2ThreadKoid2);
  debug_agent.InjectProcessForTest(std::move(process2));

  reply = {};
  remote_api->OnStatus(request, &reply);

  ASSERT_EQ(reply.processes.size(), 2u);
  EXPECT_EQ(reply.processes[0].process_koid, kProcessKoid1);
  EXPECT_EQ(reply.processes[0].process_name, kProcessName1);
  ASSERT_EQ(reply.processes[0].threads.size(), 1u);
  EXPECT_EQ(reply.processes[0].threads[0].process_koid, kProcessKoid1);
  EXPECT_EQ(reply.processes[0].threads[0].thread_koid, kProcess1ThreadKoid1);

  EXPECT_EQ(reply.processes[1].process_koid, kProcessKoid2);
  EXPECT_EQ(reply.processes[1].process_name, kProcessName2);
  ASSERT_EQ(reply.processes[1].threads.size(), 2u);
  EXPECT_EQ(reply.processes[1].threads[0].process_koid, kProcessKoid2);
  EXPECT_EQ(reply.processes[1].threads[0].thread_koid, kProcess2ThreadKoid1);
  EXPECT_EQ(reply.processes[1].threads[1].process_koid, kProcessKoid2);
  EXPECT_EQ(reply.processes[1].threads[1].thread_koid, kProcess2ThreadKoid2);

  // Set a limbo provider.
  const MockObjectProvider& object_provider = *test_context->object_provider;

  const std::string kLimboProcess1 = "job1-p1";
  const std::string kLimboProcess1Thread = "initial-thread";
  constexpr ExceptionType kLimboException1 = ExceptionType::FATAL_PAGE_FAULT;
  auto [limbo_proc1, limbo_thread1] =
      GetProcessThread(object_provider, kLimboProcess1, kLimboProcess1Thread);

  const std::string kLimboProcess2 = "job121-p2";
  const std::string kLimboProcess2Thread = "second-thread";
  constexpr ExceptionType kLimboException2 = ExceptionType::UNALIGNED_ACCESS;
  auto [limbo_proc2, limbo_thread2] =
      GetProcessThread(object_provider, kLimboProcess2, kLimboProcess2Thread);

  test_context->limbo_provider->AppendException(limbo_proc1, limbo_thread1, kLimboException1);
  test_context->limbo_provider->AppendException(limbo_proc2, limbo_thread2, kLimboException2);

  reply = {};
  remote_api->OnStatus(request, &reply);

  // The attached processes should still be there.
  ASSERT_EQ(reply.processes.size(), 2u);

  // The limbo processes should be there.
  ASSERT_EQ(reply.limbo.size(), 2u);
  EXPECT_EQ(reply.limbo[0].process_koid, limbo_proc1->koid);
  EXPECT_EQ(reply.limbo[0].process_name, limbo_proc1->name);
  ASSERT_EQ(reply.limbo[0].threads.size(), 1u);
  EXPECT_EQ(reply.limbo[0].threads[0].process_koid, limbo_proc1->koid);
  EXPECT_EQ(reply.limbo[0].threads[0].thread_koid, limbo_thread1->koid);
  EXPECT_EQ(reply.limbo[0].threads[0].name, limbo_thread1->name);
  EXPECT_EQ(reply.limbo[0].threads[0].state, debug_ipc::ThreadRecord::State::kBlocked);
  EXPECT_EQ(reply.limbo[0].threads[0].blocked_reason,
            debug_ipc::ThreadRecord::BlockedReason::kException);

  // TODO(donosoc): Add exception type.
}

TEST_F(DebugAgentTests, OnProcessStatus) {
  auto test_context = CreateTestContext();
  DebugAgent debug_agent(nullptr, ToSystemProviders(*test_context));
  debug_agent.Connect(&test_context->stream_backend.stream());
  RemoteAPI* remote_api = &debug_agent;

  constexpr uint64_t kProcessKoid1 = 0x1234;
  std::string kProcessName1 = "process-1";
  auto process1 = std::make_unique<DebugAgentMockProcess>(
      &debug_agent, kProcessKoid1, kProcessName1, test_context->object_provider,
      test_context->arch_provider);
  debug_agent.InjectProcessForTest(std::move(process1));

  constexpr uint64_t kProcessKoid2 = 0x5678;
  std::string kProcessName2 = "process-2";
  auto process2 = std::make_unique<DebugAgentMockProcess>(
      &debug_agent, kProcessKoid2, kProcessName2, test_context->object_provider,
      test_context->arch_provider);
  auto* process2_ptr = process2.get();
  debug_agent.InjectProcessForTest(std::move(process2));

  // Asking for a un-existent process should fail.
  debug_ipc::ProcessStatusRequest request = {};
  request.process_koid = 0xdeadbeef;

  debug_ipc::ProcessStatusReply reply = {};
  remote_api->OnProcessStatus(request, &reply);
  EXPECT_EQ(reply.status, (uint32_t)ZX_ERR_NOT_FOUND) << zx_status_get_string(reply.status);

  debug_ipc::NotifyModules modules_to_send = {};
  modules_to_send.process_koid = kProcessKoid2;
  modules_to_send.modules.push_back({"module-1", 0x1, 0x5, "build-1"});
  modules_to_send.modules.push_back({"module-2", 0x2, 0x7, "build-2"});
  process2_ptr->set_modules_to_send(modules_to_send);

  // Asking for an existent one should send the process and modules notification.
  request.process_koid = kProcessKoid2;
  remote_api->OnProcessStatus(request, &reply);
  EXPECT_EQ(reply.status, (uint32_t)ZX_OK) << zx_status_get_string(reply.status);

  test_context->loop.RunUntilNoTasks();

  auto& process_starts = test_context->stream_backend.process_starts();
  ASSERT_EQ(process_starts.size(), 1u);
  EXPECT_EQ(process_starts[0].koid, kProcessKoid2);
  EXPECT_EQ(process_starts[0].name, kProcessName2);

  auto& modules = test_context->stream_backend.modules();
  ASSERT_EQ(modules.size(), 1u);
  EXPECT_EQ(modules[0].process_koid, kProcessKoid2);

  ASSERT_EQ(modules[0].modules.size(), modules_to_send.modules.size());
  ASSERT_EQ(modules[0].modules[0].name, modules_to_send.modules[0].name);
  ASSERT_EQ(modules[0].modules[0].base, modules_to_send.modules[0].base);
  ASSERT_EQ(modules[0].modules[0].debug_address, modules_to_send.modules[0].debug_address);
  ASSERT_EQ(modules[0].modules[0].build_id, modules_to_send.modules[0].build_id);
  ASSERT_EQ(modules[0].modules[1].name, modules_to_send.modules[1].name);
  ASSERT_EQ(modules[0].modules[1].base, modules_to_send.modules[1].base);
  ASSERT_EQ(modules[0].modules[1].debug_address, modules_to_send.modules[1].debug_address);
  ASSERT_EQ(modules[0].modules[1].build_id, modules_to_send.modules[1].build_id);
}

TEST_F(DebugAgentTests, OnAttachNotFound) {
  uint32_t transaction_id = 1u;

  auto test_context = CreateTestContext();
  DebugAgent debug_agent(nullptr, ToSystemProviders(*test_context));
  debug_agent.Connect(&test_context->stream_backend.stream());
  RemoteAPI* remote_api = &debug_agent;

  debug_ipc::AttachRequest attach_request;
  attach_request.type = debug_ipc::TaskType::kProcess;
  attach_request.koid = -1;

  remote_api->OnAttach(transaction_id++, attach_request);

  {
    // Should've gotten an attach reply.
    auto& attach_replies = test_context->stream_backend.attach_replies();
    ASSERT_EQ(attach_replies.size(), 1u);
    EXPECT_ZX_EQ(attach_replies[0].status, ZX_ERR_NOT_FOUND);

    // There should be no attach watch.
    auto& watches = test_context->loop.watches();
    ASSERT_EQ(watches.size(), 0u);
  }

  auto [proc_object, thread_object] =
      GetProcessThread(*test_context->object_provider, "job11-p1", "second-thread");
  test_context->limbo_provider->AppendException(proc_object, thread_object,
                                                ExceptionType::FATAL_PAGE_FAULT);

  // Even with limbo it should fail.
  remote_api->OnAttach(transaction_id++, attach_request);

  {
    // Should've gotten an attach reply.
    auto& attach_replies = test_context->stream_backend.attach_replies();
    ASSERT_EQ(attach_replies.size(), 2u);
    EXPECT_ZX_EQ(attach_replies[1].status, ZX_ERR_NOT_FOUND);

    // There should be no attach watch.
    auto& watches = test_context->loop.watches();
    ASSERT_EQ(watches.size(), 0u);
  }
}

TEST_F(DebugAgentTests, OnAttach) {
  uint32_t transaction_id = 1u;

  auto test_context = CreateTestContext();
  DebugAgent debug_agent(nullptr, ToSystemProviders(*test_context));
  debug_agent.Connect(&test_context->stream_backend.stream());
  RemoteAPI* remote_api = &debug_agent;

  debug_ipc::AttachRequest attach_request;
  attach_request.type = debug_ipc::TaskType::kProcess;
  attach_request.koid = 11;

  remote_api->OnAttach(transaction_id++, attach_request);

  // We should've received a watch command (which does the low level exception watching).
  auto& watches = test_context->loop.watches();
  ASSERT_EQ(watches.size(), 1u);
  EXPECT_EQ(watches[0].process_name, "job1-p2");
  EXPECT_EQ(watches[0].process_handle, 11u);
  EXPECT_EQ(watches[0].process_koid, 11u);

  // We should've gotten an attach reply.
  auto& attach_replies = test_context->stream_backend.attach_replies();
  auto reply = attach_replies.back();
  ASSERT_EQ(attach_replies.size(), 1u);
  EXPECT_ZX_EQ(reply.status, ZX_OK);
  EXPECT_EQ(reply.koid, 11u);
  EXPECT_EQ(reply.name, "job1-p2");

  // Asking for some invalid process should fail.
  attach_request.koid = 0x231315;  // Some invalid value.
  remote_api->OnAttach(transaction_id++, attach_request);

  // We should've gotten an error reply.
  ASSERT_EQ(attach_replies.size(), 2u);
  reply = attach_replies.back();
  EXPECT_ZX_EQ(reply.status, ZX_ERR_NOT_FOUND);

  // Attaching to a third process should work.
  attach_request.koid = 21u;
  remote_api->OnAttach(transaction_id++, attach_request);

  ASSERT_EQ(attach_replies.size(), 3u);
  reply = attach_replies.back();
  EXPECT_ZX_EQ(reply.status, ZX_OK);
  EXPECT_EQ(reply.koid, 21u);
  EXPECT_EQ(reply.name, "job121-p2");

  // Attaching again to a process should fail.
  remote_api->OnAttach(transaction_id++, attach_request);

  ASSERT_EQ(attach_replies.size(), 4u);
  reply = attach_replies.back();
  EXPECT_ZX_EQ(reply.status, ZX_ERR_ALREADY_BOUND);
}

TEST_F(DebugAgentTests, AttachToLimbo) {
  uint32_t transaction_id = 1u;

  auto test_context = CreateTestContext();
  DebugAgent debug_agent(nullptr, ToSystemProviders(*test_context));
  debug_agent.Connect(&test_context->stream_backend.stream());
  RemoteAPI* remote_api = &debug_agent;

  auto [proc_object, thread_object] =
      GetProcessThread(*test_context->object_provider, "job11-p1", "second-thread");
  test_context->limbo_provider->AppendException(proc_object, thread_object,
                                                ExceptionType::FATAL_PAGE_FAULT);

  debug_ipc::AttachRequest attach_request = {};
  attach_request.type = debug_ipc::TaskType::kProcess;
  attach_request.koid = proc_object->koid;
  remote_api->OnAttach(transaction_id++, attach_request);

  // We should've received a watch command (which does the low level exception watching).
  auto& watches = test_context->loop.watches();
  ASSERT_EQ(watches.size(), 1u);
  EXPECT_EQ(watches[0].process_name, proc_object->name);
  EXPECT_EQ(watches[0].process_handle, proc_object->koid);
  EXPECT_EQ(watches[0].process_koid, proc_object->koid);

  // We should've gotten an attach reply.
  auto& attach_replies = test_context->stream_backend.attach_replies();
  auto reply = attach_replies.back();
  ASSERT_EQ(attach_replies.size(), 1u);
  EXPECT_ZX_EQ(reply.status, ZX_OK);
  EXPECT_EQ(reply.koid, proc_object->koid);
  EXPECT_EQ(reply.name, proc_object->name);

  {
    DebuggedProcess* process = debug_agent.GetDebuggedProcess(proc_object->koid);
    ASSERT_TRUE(process);
    auto threads = process->GetThreads();
    ASSERT_EQ(threads.size(), 2u);

    // Search for the exception thread.
    DebuggedThread* exception_thread = nullptr;
    for (DebuggedThread* thread : threads) {
      if (thread->koid() == thread_object->koid) {
        exception_thread = thread;
        break;
      }
    }

    ASSERT_TRUE(exception_thread);
    ASSERT_TRUE(exception_thread->IsInException());
    EXPECT_EQ(exception_thread->exception_handle()->get(), thread_object->koid);
  }
}

TEST_F(DebugAgentTests, OnEnterLimbo) {
  auto test_context = CreateTestContext();
  DebugAgent debug_agent(nullptr, ToSystemProviders(*test_context));
  debug_agent.Connect(&test_context->stream_backend.stream());

  auto [proc_object, thread_object] =
      GetProcessThread(*test_context->object_provider, "job11-p1", "second-thread");
  test_context->limbo_provider->AppendException(proc_object, thread_object,
                                                ExceptionType::FATAL_PAGE_FAULT);

  // Call the limbo.
  test_context->limbo_provider->CallOnEnterLimbo();

  // Should've sent a notification.
  {
    ASSERT_EQ(test_context->stream_backend.process_starts().size(), 1u);

    auto& process_start = test_context->stream_backend.process_starts()[0];
    EXPECT_EQ(process_start.type, debug_ipc::NotifyProcessStarting::Type::kLimbo);
    EXPECT_EQ(process_start.koid, proc_object->koid);
    EXPECT_EQ(process_start.component_id, 0u);
    EXPECT_EQ(process_start.name, proc_object->name);
  }
}

TEST_F(DebugAgentTests, DetachFromLimbo) {
  auto test_context = CreateTestContext();
  DebugAgent debug_agent(nullptr, ToSystemProviders(*test_context));
  debug_agent.Connect(&test_context->stream_backend.stream());
  RemoteAPI* remote_api = &debug_agent;

  auto [proc_object, thread_object] =
      GetProcessThread(*test_context->object_provider, "job11-p1", "second-thread");

  // Attempting to detach to a process that doesn't exist should fail.
  {
    debug_ipc::DetachRequest request = {};
    request.type = debug_ipc::TaskType::kProcess;
    request.koid = proc_object->koid;

    debug_ipc::DetachReply reply = {};
    remote_api->OnDetach(request, &reply);

    ASSERT_ZX_EQ(reply.status, ZX_ERR_NOT_FOUND);
    ASSERT_EQ(test_context->limbo_provider->release_calls().size(), 0u);
  }

  // Adding it should now find it and remove it.
  test_context->limbo_provider->AppendException(proc_object, thread_object,
                                                ExceptionType::FATAL_PAGE_FAULT);
  {
    debug_ipc::DetachRequest request = {};
    request.type = debug_ipc::TaskType::kProcess;
    request.koid = proc_object->koid;

    debug_ipc::DetachReply reply = {};
    remote_api->OnDetach(request, &reply);

    ASSERT_ZX_EQ(reply.status, ZX_OK);
    ASSERT_EQ(test_context->limbo_provider->release_calls().size(), 1u);
    EXPECT_EQ(test_context->limbo_provider->release_calls()[0], proc_object->koid);
  }

  // This should've remove it from limbo, trying it again should fail.
  {
    debug_ipc::DetachRequest request = {};
    request.type = debug_ipc::TaskType::kProcess;
    request.koid = proc_object->koid;

    debug_ipc::DetachReply reply = {};
    remote_api->OnDetach(request, &reply);

    ASSERT_ZX_EQ(reply.status, ZX_ERR_NOT_FOUND);
    ASSERT_EQ(test_context->limbo_provider->release_calls().size(), 1u);
    EXPECT_EQ(test_context->limbo_provider->release_calls()[0], proc_object->koid);
  }
}

TEST_F(DebugAgentTests, Kill) {
  uint32_t transaction_id = 1u;

  auto test_context = CreateTestContext();
  DebugAgent debug_agent(nullptr, ToSystemProviders(*test_context));
  debug_agent.Connect(&test_context->stream_backend.stream());
  RemoteAPI* remote_api = &debug_agent;

  auto [proc_object, thread_object] =
      GetProcessThread(*test_context->object_provider, "job11-p1", "second-thread");

  // Attempt to kill a process that's not there should fail.
  {
    debug_ipc::KillRequest kill_request = {};
    kill_request.process_koid = proc_object->koid;

    debug_ipc::KillReply kill_reply = {};
    remote_api->OnKill(kill_request, &kill_reply);
    ASSERT_ZX_EQ(kill_reply.status, ZX_ERR_NOT_FOUND);
  }

  // Attach to a process so that the debugger knows about it.
  {
    debug_ipc::AttachRequest attach_request = {};
    attach_request.type = debug_ipc::TaskType::kProcess;
    attach_request.koid = proc_object->koid;
    remote_api->OnAttach(transaction_id++, attach_request);

    // There should be a process.
    ASSERT_EQ(debug_agent.procs_.size(), 1u);
    // Should not come from limbo.
    EXPECT_FALSE(debug_agent.procs_.begin()->second->from_limbo());
  }

  // Killing now should work.
  {
    debug_ipc::KillRequest kill_request = {};
    kill_request.process_koid = proc_object->koid;

    debug_ipc::KillReply kill_reply = {};
    remote_api->OnKill(kill_request, &kill_reply);

    // There should be no more processes.
    ASSERT_EQ(debug_agent.procs_.size(), 0u);

    // Killing again should fail.
    remote_api->OnKill(kill_request, &kill_reply);
    ASSERT_ZX_EQ(kill_reply.status, ZX_ERR_NOT_FOUND);
  }

  // We now add the process to the limbo.
  test_context->limbo_provider->AppendException(proc_object, thread_object,
                                                ExceptionType::FATAL_PAGE_FAULT);

  // There should be no more processes.
  ASSERT_EQ(debug_agent.procs_.size(), 0u);

  // Killing now should release it.
  {
    debug_ipc::KillRequest kill_request = {};
    kill_request.process_koid = proc_object->koid;

    debug_ipc::KillReply kill_reply = {};
    remote_api->OnKill(kill_request, &kill_reply);
    ASSERT_ZX_EQ(kill_reply.status, ZX_OK);

    ASSERT_EQ(test_context->limbo_provider->release_calls().size(), 1u);
    EXPECT_EQ(test_context->limbo_provider->release_calls()[0], proc_object->koid);

    // Killing again should not find it.
    remote_api->OnKill(kill_request, &kill_reply);
    ASSERT_ZX_EQ(kill_reply.status, ZX_ERR_NOT_FOUND);
  }

  test_context->limbo_provider->AppendException(proc_object, thread_object,
                                                ExceptionType::FATAL_PAGE_FAULT);

  // This is a limbo process, so we cannot kill it.
  test_context->object_provider->set_next_kill_status(ZX_ERR_ACCESS_DENIED);

  debug_ipc::AttachRequest attach_request = {};
  attach_request.type = debug_ipc::TaskType::kProcess;
  attach_request.koid = proc_object->koid;
  remote_api->OnAttach(transaction_id++, attach_request);

  // There should be a process.
  ASSERT_EQ(debug_agent.procs_.size(), 1u);

  {
    auto it = debug_agent.procs_.find(proc_object->koid);
    ASSERT_NE(it, debug_agent.procs_.end());
    EXPECT_TRUE(debug_agent.procs_.begin()->second->from_limbo());

    // Killing it should free the process.
    debug_ipc::KillRequest kill_request = {};
    kill_request.process_koid = proc_object->koid;

    debug_ipc::KillReply kill_reply = {};
    remote_api->OnKill(kill_request, &kill_reply);
    ASSERT_ZX_EQ(kill_reply.status, ZX_OK);

    ASSERT_EQ(debug_agent.procs_.size(), 0u);

    // There should be a limbo process to be killed.
    ASSERT_EQ(debug_agent.killed_limbo_procs_.size(), 1u);
    EXPECT_EQ(debug_agent.killed_limbo_procs_.count(proc_object->koid), 1u);

    // There should've have been more release calls (yet).
    ASSERT_EQ(test_context->limbo_provider->release_calls().size(), 1u);

    // When the process "re-enters" the limbo, it should be removed.
    test_context->limbo_provider->AppendException(proc_object, thread_object,
                                                  ExceptionType::FATAL_PAGE_FAULT);
    test_context->limbo_provider->CallOnEnterLimbo();

    // There should not be an additional proc in the agent.
    ASSERT_EQ(debug_agent.procs_.size(), 0u);

    // There should've been a release call.
    ASSERT_EQ(test_context->limbo_provider->release_calls().size(), 2u);
    EXPECT_EQ(test_context->limbo_provider->release_calls()[1], proc_object->koid);
  }
}

}  // namespace debug_agent
