// 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 "src/developer/debug/zxdb/client/process_impl.h"

#include <gtest/gtest.h>

#include "src/developer/debug/zxdb/client/memory_dump.h"
#include "src/developer/debug/zxdb/client/mock_remote_api.h"
#include "src/developer/debug/zxdb/client/remote_api_test.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/target_impl.h"
#include "src/developer/debug/zxdb/symbols/elf_symbol.h"
#include "src/developer/debug/zxdb/symbols/mock_module_symbols.h"

namespace zxdb {

namespace {

class ProcessSink : public MockRemoteAPI {
 public:
  ProcessSink() = default;
  ~ProcessSink() = default;

  const debug_ipc::ResumeRequest& resume_request() const { return resume_request_; }
  int resume_count() const { return resume_count_; }

  void Resume(const debug_ipc::ResumeRequest& request,
              fit::callback<void(const Err&, debug_ipc::ResumeReply)> cb) override {
    resume_count_++;
    resume_request_ = request;
    debug::MessageLoop::Current()->PostTask(
        FROM_HERE, [cb = std::move(cb)]() mutable { cb(Err(), debug_ipc::ResumeReply()); });
  }

  // No-op.
  void Threads(const debug_ipc::ThreadsRequest& request,
               fit::callback<void(const Err&, debug_ipc::ThreadsReply)> cb) override {
    thread_request_made_ = true;
  }

  bool thread_request_made() const { return thread_request_made_; }

 private:
  debug_ipc::ResumeRequest resume_request_;
  int resume_count_ = 0;

  bool thread_request_made_ = false;
};

class ProcessImplTest : public RemoteAPITest {
 public:
  ProcessImplTest() = default;
  ~ProcessImplTest() override = default;

  ProcessSink* sink() { return sink_; }

 private:
  std::unique_ptr<RemoteAPI> GetRemoteAPIImpl() override {
    auto sink = std::make_unique<ProcessSink>();
    sink_ = sink.get();
    return sink;
  }

 private:
  ProcessSink* sink_;  // Owned by the session.
};

}  // namespace

// Tests that the correct threads are resumed after the modules are loaded.
TEST_F(ProcessImplTest, OnModules) {
  constexpr uint64_t kProcessKoid = 1234;
  Process* process = InjectProcess(kProcessKoid);
  ASSERT_TRUE(process);

  EXPECT_FALSE(sink()->thread_request_made());

  debug_ipc::NotifyModules notify;
  notify.process_koid = kProcessKoid;
  notify.modules.resize(1);
  notify.modules[0].name = "comctl32.dll";
  notify.modules[0].base = 0x7685348234;

  constexpr uint64_t kThread1Koid = 237645;
  constexpr uint64_t kThread2Koid = 809712;
  notify.stopped_threads.push_back({.process = kProcessKoid, .thread = kThread1Koid});
  notify.stopped_threads.push_back({.process = kProcessKoid, .thread = kThread2Koid});

  session().DispatchNotifyModules(notify);

  EXPECT_TRUE(sink()->thread_request_made());

  // Should have resumed both of those threads.
  ASSERT_EQ(1, sink()->resume_count());
  const debug_ipc::ResumeRequest& resume = sink()->resume_request();
  EXPECT_EQ(debug_ipc::ResumeRequest::How::kResolveAndContinue, resume.how);
  EXPECT_EQ(notify.stopped_threads, resume.ids);
}

TEST_F(ProcessImplTest, GetTLSHelpers) {
  constexpr uint64_t kProcessKoid = 1234;
  constexpr uint64_t kThreadKoid = 5678;
  constexpr char kBuildId[] = "abcd";
  constexpr uint64_t kModuleBase = 0x1000;
  Process* process = InjectProcess(kProcessKoid);
  ASSERT_TRUE(process);
  Thread* thread = InjectThread(kProcessKoid, kThreadKoid);
  ASSERT_TRUE(thread);
  SymbolContext symbol_context(kModuleBase);

  auto module_symbols = fxl::MakeRefCounted<MockModuleSymbols>("libc.so");
  session().system().GetSymbols()->InjectModuleForTesting(kBuildId, module_symbols.get());

  std::vector<debug_ipc::Module> modules;
  debug_ipc::Module module;
  module.name = "libc";
  module.base = kModuleBase;
  module.build_id = kBuildId;
  modules.push_back(module);

  TargetImpl* target = session().system().GetTargetImpls()[0];
  target->process()->OnModules(modules, {});

  constexpr uint64_t kThrdTAddr = 0x1000;
  constexpr uint64_t kLinkMapTlsModIdAddr = 0x2000;
  constexpr uint64_t kTlsBaseAddr = 0x3000;
  constexpr uint64_t kSymSize = 4;

  ElfSymbolRecord thrd_t_record(ElfSymbolType::kNormal, kThrdTAddr, kSymSize, "zxdb.thrd_t");
  ElfSymbolRecord link_map_tls_modid_record(ElfSymbolType::kNormal, kLinkMapTlsModIdAddr, kSymSize,
                                            "zxdb.link_map_tls_modid");
  ElfSymbolRecord tlsbase_record(ElfSymbolType::kNormal, kTlsBaseAddr, kSymSize, "zxdb.tlsbase");

  auto thrd_t_sym = fxl::MakeRefCounted<ElfSymbol>(module_symbols->GetWeakPtr(), thrd_t_record);
  auto link_map_tls_modid_sym =
      fxl::MakeRefCounted<ElfSymbol>(module_symbols->GetWeakPtr(), link_map_tls_modid_record);
  auto tlsbase_sym = fxl::MakeRefCounted<ElfSymbol>(module_symbols->GetWeakPtr(), tlsbase_record);

  module_symbols->AddSymbolLocations(
      Identifier(IdentifierComponent(SpecialIdentifier::kElf, "zxdb.thrd_t")),
      {Location(kThrdTAddr + kModuleBase, FileLine(), 0, symbol_context, thrd_t_sym)});
  module_symbols->AddSymbolLocations(
      Identifier(IdentifierComponent(SpecialIdentifier::kElf, "zxdb.link_map_tls_modid")),
      {Location(kLinkMapTlsModIdAddr + kModuleBase, FileLine(), 0, symbol_context,
                link_map_tls_modid_sym)});
  module_symbols->AddSymbolLocations(
      Identifier(IdentifierComponent(SpecialIdentifier::kElf, "zxdb.tlsbase")),
      {Location(kTlsBaseAddr + kModuleBase, FileLine(), 0, symbol_context, tlsbase_sym)});

  sink()->AddMemory(kThrdTAddr + kModuleBase, {0x1, 0x2, 0x3, 0x4});
  sink()->AddMemory(kLinkMapTlsModIdAddr + kModuleBase, {0x5, 0x6, 0x7, 0x8});
  sink()->AddMemory(kTlsBaseAddr + kModuleBase, {0x9, 0xa, 0xb, 0xc});

  bool called = false;
  bool called_2 = false;
  Process::TLSHelpers helpers;
  Process::TLSHelpers helpers_2;
  Err err;
  Err err_2;
  process->GetTLSHelpers([&called, &helpers, &err](ErrOr<const Process::TLSHelpers*> got) {
    called = true;

    if (got.has_error()) {
      err = got.err();
    } else {
      helpers = *got.value();
    }
  });

  process->GetTLSHelpers([&called_2, &helpers_2, &err_2](ErrOr<const Process::TLSHelpers*> got) {
    called_2 = true;

    if (got.has_error()) {
      err_2 = got.err();
    } else {
      helpers_2 = *got.value();
    }
  });

  EXPECT_FALSE(called);
  EXPECT_FALSE(called_2);
  loop().RunUntilNoTasks();
  EXPECT_TRUE(called);
  EXPECT_TRUE(called_2);
  ASSERT_FALSE(err.has_error()) << err.msg();
  EXPECT_FALSE(err_2.has_error());

  ASSERT_EQ(helpers.thrd_t.size(), kSymSize);
  ASSERT_EQ(helpers.link_map_tls_modid.size(), kSymSize);
  ASSERT_EQ(helpers.tlsbase.size(), kSymSize);

  EXPECT_EQ(0x1, helpers.thrd_t[0]);
  EXPECT_EQ(0x2, helpers.thrd_t[1]);
  EXPECT_EQ(0x3, helpers.thrd_t[2]);
  EXPECT_EQ(0x4, helpers.thrd_t[3]);

  EXPECT_EQ(0x5, helpers.link_map_tls_modid[0]);
  EXPECT_EQ(0x6, helpers.link_map_tls_modid[1]);
  EXPECT_EQ(0x7, helpers.link_map_tls_modid[2]);
  EXPECT_EQ(0x8, helpers.link_map_tls_modid[3]);

  EXPECT_EQ(0x9, helpers.tlsbase[0]);
  EXPECT_EQ(0xa, helpers.tlsbase[1]);
  EXPECT_EQ(0xb, helpers.tlsbase[2]);
  EXPECT_EQ(0xc, helpers.tlsbase[3]);

  EXPECT_EQ(0x1, helpers_2.thrd_t[0]);
  EXPECT_EQ(0x2, helpers_2.thrd_t[1]);
  EXPECT_EQ(0x3, helpers_2.thrd_t[2]);
  EXPECT_EQ(0x4, helpers_2.thrd_t[3]);

  EXPECT_EQ(0x5, helpers_2.link_map_tls_modid[0]);
  EXPECT_EQ(0x6, helpers_2.link_map_tls_modid[1]);
  EXPECT_EQ(0x7, helpers_2.link_map_tls_modid[2]);
  EXPECT_EQ(0x8, helpers_2.link_map_tls_modid[3]);

  EXPECT_EQ(0x9, helpers_2.tlsbase[0]);
  EXPECT_EQ(0xa, helpers_2.tlsbase[1]);
  EXPECT_EQ(0xb, helpers_2.tlsbase[2]);
  EXPECT_EQ(0xc, helpers_2.tlsbase[3]);

  called = false;
  process->GetTLSHelpers([&called, &helpers, &err](ErrOr<const Process::TLSHelpers*> got) {
    called = true;

    if (got.has_error()) {
      err = got.err();
    } else {
      helpers = *got.value();
    }
  });

  EXPECT_TRUE(called);
  ASSERT_FALSE(err.has_error()) << err.msg();

  ASSERT_EQ(helpers.thrd_t.size(), kSymSize);
  ASSERT_EQ(helpers.link_map_tls_modid.size(), kSymSize);
  ASSERT_EQ(helpers.tlsbase.size(), kSymSize);

  EXPECT_EQ(0x1, helpers.thrd_t[0]);
  EXPECT_EQ(0x2, helpers.thrd_t[1]);
  EXPECT_EQ(0x3, helpers.thrd_t[2]);
  EXPECT_EQ(0x4, helpers.thrd_t[3]);

  EXPECT_EQ(0x5, helpers.link_map_tls_modid[0]);
  EXPECT_EQ(0x6, helpers.link_map_tls_modid[1]);
  EXPECT_EQ(0x7, helpers.link_map_tls_modid[2]);
  EXPECT_EQ(0x8, helpers.link_map_tls_modid[3]);

  EXPECT_EQ(0x9, helpers.tlsbase[0]);
  EXPECT_EQ(0xa, helpers.tlsbase[1]);
  EXPECT_EQ(0xb, helpers.tlsbase[2]);
  EXPECT_EQ(0xc, helpers.tlsbase[3]);
}

TEST_F(ProcessImplTest, ReadMemoryAutomation) {
  constexpr uint64_t kProcessKoid = 1234;
  constexpr uint64_t kThreadKoid = 5678;
  constexpr uint64_t kBlockAddress = 0xdeadbeef;
  constexpr uint64_t kBlockSize = 8;
  Process* process = InjectProcess(kProcessKoid);
  ASSERT_TRUE(process);
  ProcessImpl* process_impl = session().system().ProcessImplFromKoid(process->GetKoid());
  ASSERT_TRUE(process_impl);

  // This creates the memory block to mimic getting a response from an automated breakpoint.
  debug_ipc::MemoryBlock mem_block = {.address = kBlockAddress, .valid = true, .size = kBlockSize};
  mem_block.data = {0, 1, 2, 3, 4, 5, 6, 7};

  debug_ipc::MemoryBlock invalid_mem_block = {
      .address = kBlockAddress + 32, .valid = false, .size = kBlockSize};
  invalid_mem_block.data = {10, 11, 12, 13, 14, 15, 16, 17};

  std::vector<debug_ipc::MemoryBlock> mem_block_vect = {mem_block, invalid_mem_block};
  process_impl->SetMemoryBlocks(kThreadKoid, mem_block_vect);

  // This puts some memory on the mock remote device such that if the read misses the memory block
  // it'll read from this array.
  sink()->AddMemory(kBlockAddress - 4, {100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
                                        112, 113, 114, 115});

  // Attempt to read the memory block. The read request must be for a subset of one of the blocks
  // returned for it to hit the memory block, otherwise it falls through to the remote device.
  process_impl->ReadMemory(
      kBlockAddress, kBlockSize, [](const zxdb::Err& err, zxdb::MemoryDump dump) {
        ASSERT_EQ(dump.blocks()[0].data, std::vector<uint8_t>({0, 1, 2, 3, 4, 5, 6, 7}));
        ASSERT_TRUE(dump.blocks()[0].valid);
      });

  // Read with a lower address, which should fall through to the remote device.
  process_impl->ReadMemory(kBlockAddress - 2, kBlockSize,
                           [](const zxdb::Err& err, zxdb::MemoryDump dump) {
                             ASSERT_EQ(dump.blocks()[0].data, std::vector<uint8_t>({
                                                                  102,
                                                                  103,
                                                                  104,
                                                                  105,
                                                                  106,
                                                                  107,
                                                                  108,
                                                                  109,
                                                              }));
                             ASSERT_TRUE(dump.blocks()[0].valid);
                           });

  // Read with a too large size, which should also fall through to the remote device.
  process_impl->ReadMemory(kBlockAddress, kBlockSize + 2,
                           [](const zxdb::Err& err, zxdb::MemoryDump dump) {
                             ASSERT_EQ(dump.blocks()[0].data, std::vector<uint8_t>({
                                                                  104,
                                                                  105,
                                                                  106,
                                                                  107,
                                                                  108,
                                                                  109,
                                                                  110,
                                                                  111,
                                                                  112,
                                                                  113,
                                                              }));
                             ASSERT_TRUE(dump.blocks()[0].valid);
                           });

  // Read a subset of the block, which should not fall through.
  process_impl->ReadMemory(kBlockAddress + 2, kBlockSize - 4,
                           [](const zxdb::Err& err, zxdb::MemoryDump dump) {
                             ASSERT_EQ(dump.blocks()[0].data, std::vector<uint8_t>({
                                                                  2,
                                                                  3,
                                                                  4,
                                                                  5,
                                                              }));
                             ASSERT_TRUE(dump.blocks()[0].valid);
                           });

  // Read a subset from the invalid block, which should not fall through, and also should not return
  // any data in the blocks.
  process_impl->ReadMemory(kBlockAddress + 32, kBlockSize - 2,
                           [](const zxdb::Err& err, zxdb::MemoryDump dump) {
                             ASSERT_EQ(dump.blocks()[0].data.size(), 0ul);
                             ASSERT_FALSE(dump.blocks()[0].valid);
                           });

  loop().RunUntilNoTasks();
}

}  // namespace zxdb
