// 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 <utility>
#include <vector>

#include "garnet/bin/debug_agent/breakpoint.h"
#include "gtest/gtest.h"

namespace debug_agent {

using CallPair = std::pair<zx_koid_t, uint64_t>;
using CallVector = std::vector<CallPair>;

class TestProcessDelegate : public Breakpoint::ProcessDelegate {
 public:
  const CallVector& register_calls() const { return register_calls_; }
  const CallVector& unregister_calls() const { return unregister_calls_; }

  void Clear() {
    register_calls_.clear();
    unregister_calls_.clear();
  }

  zx_status_t RegisterBreakpoint(Breakpoint*, zx_koid_t process_koid,
                                 uint64_t address) override {
    register_calls_.push_back(std::make_pair(process_koid, address));
    return ZX_OK;
  }
  void UnregisterBreakpoint(Breakpoint*, zx_koid_t process_koid,
                            uint64_t address) override {
    unregister_calls_.push_back(std::make_pair(process_koid, address));
  }

 private:
  CallVector register_calls_;
  CallVector unregister_calls_;
};

TEST(Breakpoint, Registration) {
  TestProcessDelegate delegate;
  Breakpoint bp(&delegate);

  debug_ipc::BreakpointSettings settings;
  settings.breakpoint_id = 1;
  settings.locations.resize(1);

  constexpr zx_koid_t kProcess1 = 1;
  constexpr uint64_t kAddress1 = 0x1234;

  debug_ipc::ProcessBreakpointSettings& pr_settings = settings.locations.back();
  pr_settings.process_koid = kProcess1;
  pr_settings.thread_koid = 0;
  pr_settings.address = kAddress1;

  // Apply the settings.
  ASSERT_EQ(ZX_OK, bp.SetSettings(settings));
  EXPECT_EQ(CallVector({CallPair{kProcess1, kAddress1}}),
            delegate.register_calls());
  EXPECT_TRUE(delegate.unregister_calls().empty());

  delegate.Clear();

  // Change the settings to move the breakpoint.
  constexpr zx_koid_t kProcess2 = 2;
  constexpr uint64_t kAddress2 = 0x5678;
  pr_settings.process_koid = kProcess2;
  pr_settings.thread_koid = 0;
  pr_settings.address = kAddress2;

  ASSERT_EQ(ZX_OK, bp.SetSettings(settings));
  EXPECT_EQ(CallVector({CallPair{kProcess2, kAddress2}}),
            delegate.register_calls());
  EXPECT_EQ(CallVector({CallPair{kProcess1, kAddress1}}),
            delegate.unregister_calls());

  // Add a new location
  delegate.Clear();

  // Add the old breakpoint and a new one
  debug_ipc::ProcessBreakpointSettings old_pr_settings;
  old_pr_settings.process_koid = kProcess1;
  old_pr_settings.thread_koid = 0;
  old_pr_settings.address = kAddress1;

  constexpr zx_koid_t kProcess3 = 3;
  constexpr uint64_t kAddress3 = 0x9ABC;

  debug_ipc::ProcessBreakpointSettings new_pr_settings;
  new_pr_settings.process_koid = kProcess3;
  new_pr_settings.thread_koid = 0;
  new_pr_settings.address = kAddress3;

  settings.locations.clear();
  settings.locations.push_back(old_pr_settings);
  settings.locations.push_back(new_pr_settings);

  ASSERT_EQ(ZX_OK, bp.SetSettings(settings));

  EXPECT_EQ(CallVector({{kProcess1, kAddress1}, {kProcess3, kAddress3}}),
            delegate.register_calls());
  EXPECT_EQ(CallVector({{kProcess2, kAddress2}}), delegate.unregister_calls());
}

// The destructor should clear breakpoint locations.
TEST(Breakpoint, Destructor) {
  TestProcessDelegate delegate;
  std::unique_ptr<Breakpoint> bp = std::make_unique<Breakpoint>(&delegate);

  debug_ipc::BreakpointSettings settings;
  settings.breakpoint_id = 1;
  settings.locations.resize(1);

  constexpr zx_koid_t kProcess1 = 1;
  constexpr uint64_t kAddress1 = 0x1234;

  debug_ipc::ProcessBreakpointSettings& pr_settings = settings.locations.back();
  pr_settings.process_koid = kProcess1;
  pr_settings.thread_koid = 0;
  pr_settings.address = kAddress1;

  // Apply the settings.
  ASSERT_EQ(ZX_OK, bp->SetSettings(settings));
  EXPECT_EQ(CallVector({CallPair{kProcess1, kAddress1}}),
            delegate.register_calls());
  EXPECT_TRUE(delegate.unregister_calls().empty());

  delegate.Clear();

  // Delete the breakpoint to make sure the locations get updated.
  delegate.Clear();
  bp.reset();
  EXPECT_EQ(CallVector({CallPair{kProcess1, kAddress1}}),
            delegate.unregister_calls());
}

TEST(Breakpoint, HitCount) {
  TestProcessDelegate delegate;
  std::unique_ptr<Breakpoint> bp = std::make_unique<Breakpoint>(&delegate);

  constexpr uint32_t kBreakpointId = 12;
  debug_ipc::BreakpointSettings settings;
  settings.breakpoint_id = kBreakpointId;
  settings.locations.resize(1);

  constexpr zx_koid_t kProcess1 = 1;
  constexpr uint64_t kAddress1 = 0x1234;

  debug_ipc::ProcessBreakpointSettings& pr_settings = settings.locations.back();
  pr_settings.process_koid = kProcess1;
  pr_settings.thread_koid = 0;
  pr_settings.address = kAddress1;

  // Apply the settings.
  ASSERT_EQ(ZX_OK, bp->SetSettings(settings));
  delegate.Clear();

  EXPECT_EQ(kBreakpointId, bp->stats().breakpoint_id);
  EXPECT_EQ(0u, bp->stats().hit_count);

  EXPECT_EQ(Breakpoint::HitResult::kHit, bp->OnHit());
  EXPECT_EQ(kBreakpointId, bp->stats().breakpoint_id);
  EXPECT_EQ(1u, bp->stats().hit_count);
  EXPECT_FALSE(bp->stats().should_delete);

  EXPECT_EQ(Breakpoint::HitResult::kHit, bp->OnHit());
  EXPECT_EQ(kBreakpointId, bp->stats().breakpoint_id);
  EXPECT_EQ(2u, bp->stats().hit_count);
  EXPECT_FALSE(bp->stats().should_delete);
}

TEST(Breakpoint, OneShot) {
  TestProcessDelegate delegate;
  std::unique_ptr<Breakpoint> bp = std::make_unique<Breakpoint>(&delegate);

  constexpr uint32_t kBreakpointId = 12;
  debug_ipc::BreakpointSettings settings;
  settings.breakpoint_id = kBreakpointId;
  settings.one_shot = true;
  settings.locations.resize(1);

  constexpr zx_koid_t kProcess = 1;
  constexpr uint64_t kAddress = 0x1234;

  debug_ipc::ProcessBreakpointSettings& pr_settings = settings.locations.back();
  pr_settings.process_koid = kProcess;
  pr_settings.thread_koid = 0;
  pr_settings.address = kAddress;

  // Apply the settings.
  ASSERT_EQ(ZX_OK, bp->SetSettings(settings));
  delegate.Clear();

  EXPECT_EQ(kBreakpointId, bp->stats().breakpoint_id);
  EXPECT_EQ(0u, bp->stats().hit_count);
  EXPECT_FALSE(bp->stats().should_delete);

  // The hit count and "should delete" flag should be set.
  EXPECT_EQ(Breakpoint::HitResult::kOneShotHit, bp->OnHit());
  EXPECT_EQ(kBreakpointId, bp->stats().breakpoint_id);
  EXPECT_EQ(1u, bp->stats().hit_count);
  EXPECT_TRUE(bp->stats().should_delete);
}

}  // namespace debug_agent
