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

#include <gtest/gtest.h>

#include "src/developer/debug/debug_agent/breakpoint.h"
#include "src/developer/debug/debug_agent/mock_arch_provider.h"
#include "src/developer/debug/debug_agent/mock_process.h"
#include "src/developer/debug/debug_agent/mock_thread.h"

namespace debug_agent {
namespace {

using AddressRange = ::debug_ipc::AddressRange;

class MockProcessDelegate : public Breakpoint::ProcessDelegate {
 public:
  zx_status_t RegisterBreakpoint(Breakpoint*, zx_koid_t, uint64_t) override { return ZX_OK; }
  void UnregisterBreakpoint(Breakpoint* bp, zx_koid_t process_koid, uint64_t address) override {}

  zx_status_t RegisterWatchpoint(Breakpoint*, zx_koid_t, const debug_ipc::AddressRange&) override {
    return ZX_OK;
  }
  void UnregisterWatchpoint(Breakpoint*, zx_koid_t, const debug_ipc::AddressRange&) override {}
};

class MockWatchpointArchProvider : public MockArchProvider {
 public:
  struct Installation {
    zx_koid_t thread_koid;
    AddressRange address_range;
    debug_ipc::BreakpointType type;
  };

  arch::WatchpointInstallationResult InstallWatchpoint(debug_ipc::BreakpointType type,
                                                       const zx::thread& thread,
                                                       const AddressRange& range) override {
    installs_.push_back({thread.get(), range, type});
    return arch::WatchpointInstallationResult(ZX_OK, range_to_return_, slot_to_return_);
  }

  zx_status_t UninstallWatchpoint(const zx::thread& thread, const AddressRange& range) override {
    // Uninstalls don't need type.
    uninstalls_.push_back({thread.get(), range, debug_ipc::BreakpointType::kLast});
    return ZX_OK;
  }

  const std::vector<Installation>& installs() const { return installs_; }
  const std::vector<Installation>& uninstalls() const { return uninstalls_; }

  void set_range_to_return(debug_ipc::AddressRange r) { range_to_return_ = r; }
  void set_slot_to_return(int slot) { slot_to_return_ = slot; }

 private:
  std::vector<Installation> installs_;
  std::vector<Installation> uninstalls_;

  debug_ipc::AddressRange range_to_return_;
  int slot_to_return_ = 0;
};

// If |thread| is null, it means a process-wide breakpoint.
debug_ipc::ProcessBreakpointSettings CreateLocation(const MockProcess& process,
                                                    const MockThread* thread,
                                                    const debug_ipc::AddressRange& range) {
  debug_ipc::ProcessBreakpointSettings location = {};
  location.process_koid = process.koid();
  if (thread)
    location.thread_koid = thread->koid();
  location.address = 0;
  location.address_range = range;

  return location;
}

bool ContainsKoids(const Watchpoint& watchpoint, const std::vector<zx_koid_t>& koids) {
  auto& installed_koids = watchpoint.installed_threads();
  if (installed_koids.size() != koids.size()) {
    ADD_FAILURE() << "Expected " << koids.size() << " koids, got " << installed_koids.size();
    return false;
  }

  for (zx_koid_t koid : koids) {
    if (installed_koids.count(koid) == 0) {
      ADD_FAILURE() << "Expected koid " << koid << " to be present.";
      return false;
    }
  }

  return true;
}

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

const AddressRange kAddressRange = {0x1000, 0x2000};

TEST(Watchpoint, SimpleInstallAndRemove) {
  auto arch_provider = std::make_shared<MockWatchpointArchProvider>();
  auto object_provider = std::make_shared<ObjectProvider>();

  MockProcess process(nullptr, 0x1, "process", arch_provider, object_provider);
  MockThread* thread1 = process.AddThread(0x1001);

  MockProcessDelegate process_delegate;

  debug_ipc::BreakpointSettings settings;
  settings.type = debug_ipc::BreakpointType::kWrite;
  settings.locations.push_back(CreateLocation(process, thread1, kAddressRange));

  Breakpoint breakpoint1(&process_delegate);
  breakpoint1.SetSettings(settings);

  Watchpoint watchpoint(debug_ipc::BreakpointType::kWrite, &breakpoint1, &process, arch_provider,
                        kAddressRange);
  ASSERT_EQ(watchpoint.breakpoints().size(), 1u);

  // Update should install one thread
  ASSERT_EQ(watchpoint.Update(), ZX_OK);
  ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid()}));

  ASSERT_EQ(arch_provider->installs().size(), 1u);
  EXPECT_EQ(arch_provider->installs()[0].thread_koid, thread1->koid());
  EXPECT_EQ(arch_provider->installs()[0].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[0].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->uninstalls().size(), 0u);

  // Binding again to the same breakpoint should fail.

  ASSERT_EQ(watchpoint.RegisterBreakpoint(&breakpoint1), ZX_ERR_ALREADY_BOUND);
  ASSERT_EQ(watchpoint.breakpoints().size(), 1u);

  // Unregistering the breakpoint should issue an uninstall. As there are no more breakpoints,
  // unregistering should return false.

  ASSERT_FALSE(watchpoint.UnregisterBreakpoint(&breakpoint1));
  ASSERT_EQ(watchpoint.breakpoints().size(), 0u);
  ASSERT_TRUE(ContainsKoids(watchpoint, {}));

  ASSERT_EQ(arch_provider->installs().size(), 1u);
  EXPECT_EQ(arch_provider->uninstalls().size(), 1u);
  EXPECT_EQ(arch_provider->uninstalls()[0].thread_koid, thread1->koid());
  EXPECT_EQ(arch_provider->uninstalls()[0].address_range, kAddressRange);

  // Registering again should add the breakpoint again.

  ASSERT_EQ(watchpoint.RegisterBreakpoint(&breakpoint1), ZX_OK);
  ASSERT_EQ(watchpoint.breakpoints().size(), 1u);
  ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid()}));

  ASSERT_EQ(arch_provider->installs().size(), 2u);
  EXPECT_EQ(arch_provider->installs()[1].thread_koid, thread1->koid());
  EXPECT_EQ(arch_provider->installs()[1].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[1].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->uninstalls().size(), 1u);

  // Create two other threads.

  MockThread* thread2 = process.AddThread(0x1002);
  MockThread* thread3 = process.AddThread(0x1003);

  // Create a breakpoint that targets the second thread with the correct size.
  // Registering the breakpoint should only add one more install.

  debug_ipc::BreakpointSettings settings2;
  settings2.type = debug_ipc::BreakpointType::kWrite;
  settings2.locations.push_back(CreateLocation(process, thread2, kAddressRange));
  debug_ipc::AddressRange address_range2(kAddressRange.begin(), kAddressRange.end() + 8);
  settings2.locations.push_back(CreateLocation(process, thread3, address_range2));

  Breakpoint breakpoint2(&process_delegate);
  breakpoint2.SetSettings(settings2);

  ASSERT_EQ(watchpoint.RegisterBreakpoint(&breakpoint2), ZX_OK);
  ASSERT_EQ(watchpoint.breakpoints().size(), 2u);
  ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid(), thread2->koid()}));

  ASSERT_EQ(arch_provider->installs().size(), 3u);
  EXPECT_EQ(arch_provider->installs()[2].thread_koid, thread2->koid());
  EXPECT_EQ(arch_provider->installs()[2].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[2].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->uninstalls().size(), 1u);

  // Removing the first breakpoint should remove the first install.
  // Returning true means that there are more breakpoints registered.

  ASSERT_TRUE(watchpoint.UnregisterBreakpoint(&breakpoint1));
  ASSERT_EQ(watchpoint.breakpoints().size(), 1u);
  ASSERT_TRUE(ContainsKoids(watchpoint, {thread2->koid()}));

  ASSERT_EQ(arch_provider->installs().size(), 3u);
  EXPECT_EQ(arch_provider->uninstalls().size(), 2u);
  EXPECT_EQ(arch_provider->uninstalls()[1].thread_koid, thread1->koid());
  EXPECT_EQ(arch_provider->uninstalls()[1].address_range, kAddressRange);

  // Add a location for another address to the already bound breakpoint.
  // Add a location to the already bound breakpoint.

  settings2.locations.push_back(CreateLocation(process, thread3, kAddressRange));
  breakpoint2.SetSettings(settings2);

  // Updating should've only installed for the third thread.

  ASSERT_EQ(watchpoint.Update(), ZX_OK);
  ASSERT_TRUE(ContainsKoids(watchpoint, {thread2->koid(), thread3->koid()}));

  ASSERT_EQ(arch_provider->installs().size(), 4u);
  EXPECT_EQ(arch_provider->installs()[3].thread_koid, thread3->koid());
  EXPECT_EQ(arch_provider->installs()[3].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[3].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->uninstalls().size(), 2u);

  // Create moar threads.

  MockThread* thread4 = process.AddThread(0x1004);
  MockThread* thread5 = process.AddThread(0x1005);
  MockThread* thread6 = process.AddThread(0x1006);

  // Create a breakpoint that spans all locations.

  debug_ipc::BreakpointSettings settings3;
  settings3.type = debug_ipc::BreakpointType::kWrite;
  settings3.locations.push_back(CreateLocation(process, nullptr, kAddressRange));

  Breakpoint breakpoint3(&process_delegate);
  breakpoint3.SetSettings(settings3);

  // Registering the breakpoint should add a breakpoint for all threads, but only updating the ones
  // that are not currently installed.

  ASSERT_EQ(watchpoint.RegisterBreakpoint(&breakpoint3), ZX_OK);
  ASSERT_EQ(watchpoint.breakpoints().size(), 2u);
  ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid(), thread2->koid(), thread3->koid(),
                                         thread4->koid(), thread5->koid(), thread6->koid()}));

  ASSERT_EQ(arch_provider->installs().size(), 8u);
  EXPECT_EQ(arch_provider->installs()[4].thread_koid, thread1->koid());
  EXPECT_EQ(arch_provider->installs()[4].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[4].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->installs()[5].thread_koid, thread4->koid());
  EXPECT_EQ(arch_provider->installs()[5].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[5].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->installs()[6].thread_koid, thread5->koid());
  EXPECT_EQ(arch_provider->installs()[6].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[6].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->installs()[7].thread_koid, thread6->koid());
  EXPECT_EQ(arch_provider->installs()[7].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[7].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->uninstalls().size(), 2u);

  // Removing the other breakpoint should not remove installs.

  ASSERT_TRUE(watchpoint.UnregisterBreakpoint(&breakpoint2));
  ASSERT_EQ(watchpoint.breakpoints().size(), 1u);

  ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid(), thread2->koid(), thread3->koid(),
                                         thread4->koid(), thread5->koid(), thread6->koid()}));

  ASSERT_EQ(arch_provider->installs().size(), 8u);
  EXPECT_EQ(arch_provider->uninstalls().size(), 2u);

  // Removing the last breakpoint should remove all the installations.
  // Returns false because there are no more registered breakpoints.

  ASSERT_FALSE(watchpoint.UnregisterBreakpoint(&breakpoint3));
  ASSERT_EQ(watchpoint.breakpoints().size(), 0u);

  ASSERT_TRUE(ContainsKoids(watchpoint, {}));

  ASSERT_EQ(arch_provider->installs().size(), 8u);
  EXPECT_EQ(arch_provider->uninstalls().size(), 8u);
  EXPECT_EQ(arch_provider->uninstalls()[2].thread_koid, thread1->koid());
  EXPECT_EQ(arch_provider->uninstalls()[2].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->uninstalls()[3].thread_koid, thread2->koid());
  EXPECT_EQ(arch_provider->uninstalls()[3].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->uninstalls()[4].thread_koid, thread3->koid());
  EXPECT_EQ(arch_provider->uninstalls()[4].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->uninstalls()[5].thread_koid, thread4->koid());
  EXPECT_EQ(arch_provider->uninstalls()[5].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->uninstalls()[6].thread_koid, thread5->koid());
  EXPECT_EQ(arch_provider->uninstalls()[6].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->uninstalls()[7].thread_koid, thread6->koid());
  EXPECT_EQ(arch_provider->uninstalls()[7].address_range, kAddressRange);
}

TEST(Watchpoint, InstalledRanges) {
  auto arch_provider = std::make_shared<MockWatchpointArchProvider>();
  auto object_provider = std::make_shared<ObjectProvider>();

  MockProcess process(nullptr, 0x1, "process", arch_provider, object_provider);
  MockThread* thread1 = process.AddThread(0x1001);

  MockProcessDelegate process_delegate;

  debug_ipc::BreakpointSettings settings;
  settings.type = debug_ipc::BreakpointType::kWrite;
  settings.locations.push_back(CreateLocation(process, thread1, kAddressRange));

  Breakpoint breakpoint1(&process_delegate);
  breakpoint1.SetSettings(settings);

  Watchpoint watchpoint(debug_ipc::BreakpointType::kWrite, &breakpoint1, &process, arch_provider,
                        kAddressRange);
  ASSERT_EQ(watchpoint.breakpoints().size(), 1u);

  const debug_ipc::AddressRange kSubRange = {0x900, 0x2100};
  constexpr int kSlot = 1;
  arch_provider->set_range_to_return(kSubRange);
  arch_provider->set_slot_to_return(kSlot);

  // Update should install one thread
  ASSERT_EQ(watchpoint.Update(), ZX_OK);
  ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid()}));

  // There should be an install with a different sub range.
  ASSERT_EQ(arch_provider->installs().size(), 1u);
  EXPECT_EQ(arch_provider->installs()[0].thread_koid, thread1->koid());
  EXPECT_EQ(arch_provider->installs()[0].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->installs()[0].type, debug_ipc::BreakpointType::kWrite);
  EXPECT_EQ(arch_provider->uninstalls().size(), 0u);

  // The installed and actual range should be differnt.
  {
    auto& installations = watchpoint.installed_threads();

    ASSERT_EQ(installations.size(), 1u);

    auto it = installations.find(thread1->koid());
    ASSERT_NE(it, installations.end());
    EXPECT_EQ(it->second.status, ZX_OK) << zx_status_get_string(it->second.status);
    EXPECT_EQ(it->second.installed_range, kSubRange);
    EXPECT_EQ(it->second.slot, kSlot);
  }
}

TEST(Watchpoint, MatchesException) {
  auto arch_provider = std::make_shared<MockWatchpointArchProvider>();
  auto object_provider = std::make_shared<ObjectProvider>();

  MockProcess process(nullptr, 0x1, "process", arch_provider, object_provider);
  MockThread* thread1 = process.AddThread(0x1001);
  MockThread* thread2 = process.AddThread(0x1002);

  MockProcessDelegate process_delegate;

  debug_ipc::BreakpointSettings settings;
  settings.type = debug_ipc::BreakpointType::kWrite;
  settings.locations.push_back(CreateLocation(process, thread1, kAddressRange));

  Breakpoint breakpoint1(&process_delegate);
  breakpoint1.SetSettings(settings);

  Watchpoint watchpoint(debug_ipc::BreakpointType::kWrite, &breakpoint1, &process, arch_provider,
                        kAddressRange);
  ASSERT_EQ(watchpoint.breakpoints().size(), 1u);

  const debug_ipc::AddressRange kSubRange = {0x900, 0x2100};
  constexpr int kSlot = 1;
  arch_provider->set_range_to_return(kSubRange);
  arch_provider->set_slot_to_return(kSlot);

  // Update should install one thread
  ASSERT_EQ(watchpoint.Update(), ZX_OK);
  ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid()}));

  // There should be an install with a different sub range.
  ASSERT_EQ(arch_provider->installs().size(), 1u);
  EXPECT_EQ(arch_provider->installs()[0].thread_koid, thread1->koid());
  EXPECT_EQ(arch_provider->installs()[0].address_range, kAddressRange);
  EXPECT_EQ(arch_provider->uninstalls().size(), 0u);

  // The installed and actual range should be differnt.
  {
    auto& installations = watchpoint.installed_threads();

    ASSERT_EQ(installations.size(), 1u);

    auto it = installations.find(thread1->koid());
    ASSERT_NE(it, installations.end());
    EXPECT_EQ(it->second.status, ZX_OK) << zx_status_get_string(it->second.status);
    EXPECT_EQ(it->second.installed_range, kSubRange);
    EXPECT_EQ(it->second.slot, kSlot);

    // Only same slot and within range should work.
    EXPECT_FALSE(watchpoint.MatchesException(thread1->koid(), kSubRange.begin() - 1, kSlot));
    EXPECT_TRUE(watchpoint.MatchesException(thread1->koid(), kSubRange.begin(), kSlot));
    EXPECT_TRUE(watchpoint.MatchesException(thread1->koid(), kSubRange.begin() + 1, kSlot));
    EXPECT_TRUE(watchpoint.MatchesException(thread1->koid(), kSubRange.end() - 1, kSlot));
    EXPECT_FALSE(watchpoint.MatchesException(thread1->koid(), kSubRange.end(), kSlot));

    // Different slot should fail.
    EXPECT_FALSE(watchpoint.MatchesException(thread1->koid(), kSubRange.begin(), kSlot + 1));

    // Different thread should fail.
    EXPECT_FALSE(watchpoint.MatchesException(thread2->koid(), kSubRange.begin(), kSlot));
  }
}

TEST(Watchpoint, DifferentTypes) {
  auto arch_provider = std::make_shared<MockWatchpointArchProvider>();
  auto object_provider = std::make_shared<ObjectProvider>();

  MockProcess process(nullptr, 0x1, "process", arch_provider, object_provider);
  MockThread* thread1 = process.AddThread(0x1001);

  MockProcessDelegate process_delegate;

  debug_ipc::BreakpointSettings settings;
  settings.locations.push_back(CreateLocation(process, thread1, kAddressRange));

  {
    Breakpoint breakpoint1(&process_delegate);
    settings.type = debug_ipc::BreakpointType::kWrite;
    breakpoint1.SetSettings(settings);

    Watchpoint watchpoint(debug_ipc::BreakpointType::kWrite, &breakpoint1, &process, arch_provider,
                          kAddressRange);
    ASSERT_EQ(watchpoint.breakpoints().size(), 1u);

    ASSERT_EQ(watchpoint.Update(), ZX_OK);
    ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid()}));

    // There should be an install with a different sub range.
    ASSERT_EQ(arch_provider->installs().size(), 1u);
    EXPECT_EQ(arch_provider->installs()[0].thread_koid, thread1->koid());
    EXPECT_EQ(arch_provider->installs()[0].address_range, kAddressRange);
    EXPECT_EQ(arch_provider->installs()[0].type, debug_ipc::BreakpointType::kWrite);
  }

  {
    Breakpoint breakpoint1(&process_delegate);
    settings.type = debug_ipc::BreakpointType::kReadWrite;
    breakpoint1.SetSettings(settings);

    Watchpoint watchpoint(debug_ipc::BreakpointType::kReadWrite, &breakpoint1, &process,
                          arch_provider, kAddressRange);
    ASSERT_EQ(watchpoint.breakpoints().size(), 1u);

    ASSERT_EQ(watchpoint.Update(), ZX_OK);
    ASSERT_TRUE(ContainsKoids(watchpoint, {thread1->koid()}));

    // There should be an install with a different sub range.
    ASSERT_EQ(arch_provider->installs().size(), 2u);
    EXPECT_EQ(arch_provider->installs()[1].thread_koid, thread1->koid());
    EXPECT_EQ(arch_provider->installs()[1].address_range, kAddressRange);
    EXPECT_EQ(arch_provider->installs()[1].type, debug_ipc::BreakpointType::kReadWrite);
  }
}

}  // namespace
}  // namespace debug_agent
