// 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 "garnet/bin/debug_agent/process_watchpoint.h"

#include <gtest/gtest.h>

#include "garnet/bin/debug_agent/debugged_process.h"
#include "garnet/bin/debug_agent/debugged_thread.h"
#include "garnet/bin/debug_agent/mock_arch_provider.h"
#include "garnet/bin/debug_agent/mock_process.h"
#include "garnet/bin/debug_agent/process_watchpoint.h"
#include "garnet/bin/debug_agent/watchpoint.h"
#include "garnet/lib/debug_ipc/helper/zx_status.h"

namespace debug_agent {

namespace {

// A no-op process delegate.
class TestProcessDelegate : public Watchpoint::ProcessDelegate {
 public:
  using WatchpointMap =
      std::multimap<debug_ipc::AddressRange, std::unique_ptr<ProcessWatchpoint>,
               debug_ipc::AddressRangeCompare>;

  const WatchpointMap& watchpoint_map() const { return wps_; }

  void InjectMockProcess(std::unique_ptr<MockProcess> proc) {
    procs_[proc->koid()] = std::move(proc);
  }

  // This only gets called if Breakpoint.SetSettings() is called.
  zx_status_t RegisterWatchpoint(Watchpoint* wp, zx_koid_t process_koid,
                                 const debug_ipc::AddressRange& range) override {
    auto proc_it = procs_.find(process_koid);
    FXL_DCHECK(proc_it != procs_.end());

    auto found = wps_.find(range);
    if (found != wps_.end())
      return ZX_ERR_INTERNAL;
    auto pwp =
        std::make_unique<ProcessWatchpoint>(wp, proc_it->second.get(), range);

    zx_status_t status = pwp->Init();
    if (status != ZX_OK) {
      FXL_LOG(ERROR) << "Failure initializing: "
                     << debug_ipc::ZxStatusToString(status);
      return status;
    }

    wps_.insert({range, std::move(pwp)});

    return ZX_OK;
  }

  void UnregisterWatchpoint(Watchpoint* wp, zx_koid_t process_koid,
                            const debug_ipc::AddressRange& range) override {
    // The destructor of the watchpoint will call the arch removal.
    size_t remove_count = wps_.erase(range);
    if (remove_count == 0)
      GTEST_FAIL();
  }

 private:

  WatchpointMap wps_;
  std::map<zx_koid_t, std::unique_ptr<MockProcess>> procs_;
};

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

constexpr zx_koid_t kProcessId1 = 0x1;
constexpr zx_koid_t kProcessId2 = 0x2;
constexpr zx_koid_t kThreadId11 = 0x1;
constexpr zx_koid_t kThreadId12 = 0x2;
constexpr zx_koid_t kThreadId13 = 0x3;

constexpr zx_koid_t kThreadId21 = 0x4;
constexpr zx_koid_t kThreadId22 = 0x5;
constexpr zx_koid_t kThreadId23 = 0x6;
constexpr zx_koid_t kThreadId24 = 0x7;
constexpr zx_koid_t kThreadId25 = 0x8;

constexpr debug_ipc::AddressRange kAddressRange1 = {0x1000, 0x2000};
constexpr debug_ipc::AddressRange kAddressRange2 = {0x4000, 0x8000};

TEST(ProcessWatchpoint, InstallAndRemove) {
  ScopedMockArchProvider scoped_arch_provider;
  MockArchProvider* arch_provider = scoped_arch_provider.get_provider();

  TestProcessDelegate process_delegate;

  auto process1 = std::make_unique<MockProcess>(kProcessId1);
  process1->AddThread(kThreadId11);
  process1->AddThread(kThreadId12);
  process1->AddThread(kThreadId13);
  process_delegate.InjectMockProcess(std::move(process1));

  auto process2 = std::make_unique<MockProcess>(kProcessId2);
  process2->AddThread(kThreadId21);
  process2->AddThread(kThreadId22);
  process2->AddThread(kThreadId23);
  process2->AddThread(kThreadId24);
  process2->AddThread(kThreadId25);
  process_delegate.InjectMockProcess(std::move(process2));

  auto watchpoint = std::make_unique<Watchpoint>(&process_delegate);

  // Insert the watchpoint for all threads.
  debug_ipc::WatchpointSettings settings = {};
  settings.watchpoint_id = 0x1;
  settings.locations.push_back({kProcessId1, kThreadId11, kAddressRange1});
  settings.locations.push_back({kProcessId1, kThreadId13, kAddressRange1});
  // All of the process 2 threads.
  settings.locations.push_back({kProcessId2, 0, kAddressRange2});

  zx_status_t res = watchpoint->SetSettings(settings);
  ASSERT_EQ(res, ZX_OK) << "Expected ZX_OK, got: "
                        << debug_ipc::ZxStatusToString(res);

  // Should have installed only one process watchpoint per process.
  const auto& watchpoint_map = process_delegate.watchpoint_map();
  ASSERT_EQ(watchpoint_map.count(kAddressRange1), 1u);
  ASSERT_EQ(watchpoint_map.count(kAddressRange2), 1u);

  // It should have installed 2 thread installations for process 1
  EXPECT_EQ(arch_provider->WatchpointInstallCount(kAddressRange1), 2u);

  // It should have installed 5 thread installations for process 1
  EXPECT_EQ(arch_provider->WatchpointInstallCount(kAddressRange2), 5u);

  // Once removed, we expect everything to go away.
  watchpoint.reset();

  ASSERT_EQ(watchpoint_map.count(kAddressRange1), 0u);
  ASSERT_EQ(watchpoint_map.count(kAddressRange2), 0u);
  EXPECT_EQ(arch_provider->WatchpointUninstallCount(kAddressRange1), 2u);
  EXPECT_EQ(arch_provider->WatchpointUninstallCount(kAddressRange2), 5u);
}

}  // namespace

}  // namespace debug_agent
