// 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/zxdb/client/thread_controller.h"

#include "src/developer/debug/zxdb/client/inline_thread_controller_test.h"
#include "src/developer/debug/zxdb/client/mock_frame.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/stack.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/symbols/function.h"

namespace zxdb {

namespace {

// Provide an implementation of the ThreadController's pure virtual functions so we can instantiate
// it.
class DummyThreadController : public ThreadController {
 public:
  DummyThreadController() = default;
  ~DummyThreadController() = default;

  // ThreadController implementation.
  void InitWithThread(Thread* thread, fit::callback<void(const Err&)> cb) override {
    SetThread(thread);
    cb(Err());
  }
  ContinueOp GetContinueOp() override { return ContinueOp::StepInstruction(); }
  StopOp OnThreadStop(debug_ipc::ExceptionType stop_type,
                      const std::vector<fxl::WeakPtr<Breakpoint>>& hit_breakpoints) override {
    return kStopDone;
  }
  const char* GetName() const override { return "Dummy"; }

  // Make public for the test to use.
  using ThreadController::InlineFrameIs;
  using ThreadController::SetInlineFrameIfAmbiguous;
};

// Can't be called "ThreadControllerTest" because that's the base class for all
// thread-controller-related tests. We need the inline harness since we want to test the inline
// frame handling.
class ThreadControllerUnitTest : public InlineThreadControllerTest {};

}  // namespace

TEST_F(ThreadControllerUnitTest, SetInlineFrameIfAmbiguous) {
  // The mock stack has 6 entries, we want to test ambiguous inline frames so lop off the top two.
  // This will leave the "middle" function with its two nested inlines starting at the same address
  // as being the top.
  auto mock_frames = GetStack();
  mock_frames.erase(mock_frames.begin(), mock_frames.begin() + 2);

  SymbolContext symbol_context = mock_frames[0]->GetLocation().symbol_context();

  // Make the now-exposed top two frames have an ambiguous location (address at the beginning of
  // their code range). This isn't the case in the default test data (inline frames not at the top
  // of the stack can't be ambiguous because the physical call requires some instructions).
  uint64_t address = kMiddleInline2FunctionRange.begin();
  mock_frames[0]->SetAddress(address);
  mock_frames[0]->set_is_ambiguous_inline(true);
  mock_frames[1]->SetAddress(address);
  mock_frames[1]->set_is_ambiguous_inline(true);

  // The top two frames should have the same start address of the function range, and the same code
  // address (this is testing that the harness has set things up the way we need). The physical
  // frame below them (index 2) should also have the same code address.
  ASSERT_EQ(
      kMiddleInline2FunctionRange,
      mock_frames[0]->GetLocation().symbol().Get()->As<Function>()->GetFullRange(symbol_context));
  ASSERT_EQ(
      kMiddleInline1FunctionRange,
      mock_frames[1]->GetLocation().symbol().Get()->As<Function>()->GetFullRange(symbol_context));
  ASSERT_EQ(kMiddleInline1FunctionRange.begin(), address);
  ASSERT_EQ(kMiddleInline2FunctionRange.begin(), address);

  // Set the stack.
  InjectExceptionWithStack(process()->GetKoid(), thread()->GetKoid(),
                           debug_ipc::ExceptionType::kSingleStep,
                           MockFrameVectorToFrameVector(std::move(mock_frames)), true);

  // Check the initial state of the inline frames on the stack. This is also pre-test validation.
  // There should be two inline frames and neither should be hidden.
  Stack& stack = thread()->GetStack();
  ASSERT_EQ(2u, stack.GetAmbiguousInlineFrameCount());
  ASSERT_EQ(0u, stack.hide_ambiguous_inline_frame_count());

  FrameFingerprint inline_2_fingerprint = stack.GetFrameFingerprint(0);
  FrameFingerprint inline_1_fingerprint = stack.GetFrameFingerprint(1);
  FrameFingerprint physical_fingerprint = stack.GetFrameFingerprint(2);

  // Supply a frame fingerprint that's not in the stack. This should be ignored.
  DummyThreadController controller;
  controller.InitWithThread(thread(), [](const Err&) {});
  controller.SetInlineFrameIfAmbiguous(DummyThreadController::InlineFrameIs::kEqual,
                                       FrameFingerprint(0x1234567, 0));
  EXPECT_EQ(2u, stack.GetAmbiguousInlineFrameCount());
  EXPECT_EQ(0u, stack.hide_ambiguous_inline_frame_count());

  // Supply the top frame fingerprint, this should also do nothing since it's
  // already the top one.
  controller.SetInlineFrameIfAmbiguous(DummyThreadController::InlineFrameIs::kEqual,
                                       inline_2_fingerprint);
  EXPECT_EQ(2u, stack.GetAmbiguousInlineFrameCount());
  EXPECT_EQ(0u, stack.hide_ambiguous_inline_frame_count());

  // Set previous to the top frame, it should hide the top frame.
  controller.SetInlineFrameIfAmbiguous(DummyThreadController::InlineFrameIs::kOneBefore,
                                       inline_2_fingerprint);
  EXPECT_EQ(1u, stack.hide_ambiguous_inline_frame_count());

  // The inline frame 1 fingerprint should hide the top inline frame.
  controller.SetInlineFrameIfAmbiguous(DummyThreadController::InlineFrameIs::kEqual,
                                       inline_1_fingerprint);
  EXPECT_EQ(2u, stack.GetAmbiguousInlineFrameCount());
  EXPECT_EQ(1u, stack.hide_ambiguous_inline_frame_count());

  // Set previous to inline frame 1, it should hide two frames.
  controller.SetInlineFrameIfAmbiguous(DummyThreadController::InlineFrameIs::kOneBefore,
                                       inline_1_fingerprint);
  EXPECT_EQ(2u, stack.hide_ambiguous_inline_frame_count());

  // Top physical frame should hide both inline frames.
  controller.SetInlineFrameIfAmbiguous(DummyThreadController::InlineFrameIs::kEqual,
                                       physical_fingerprint);
  EXPECT_EQ(2u, stack.GetAmbiguousInlineFrameCount());
  EXPECT_EQ(2u, stack.hide_ambiguous_inline_frame_count());

  // Go back to the frame 1 fingerprint. This should work even though its currently hidden.
  controller.SetInlineFrameIfAmbiguous(DummyThreadController::InlineFrameIs::kEqual,
                                       inline_1_fingerprint);
  EXPECT_EQ(1u, stack.hide_ambiguous_inline_frame_count());

  // Set previous to the top physical frame should be invalid because it's not ambiguous (there's a
  // physical frame in the way). As a result, the hide count should be unchanged from before.
  controller.SetInlineFrameIfAmbiguous(DummyThreadController::InlineFrameIs::kOneBefore,
                                       physical_fingerprint);
  EXPECT_EQ(1u, stack.hide_ambiguous_inline_frame_count());

  // Make a case that's not ambiguous because the current location isn't at the top of the beginning
  // of an inline function range.
  mock_frames = GetStack();
  mock_frames.erase(mock_frames.begin(), mock_frames.begin() + 2);
  mock_frames[0]->SetAddress(mock_frames[0]->GetAddress() + 4);
  mock_frames[0]->set_is_ambiguous_inline(false);
  InjectExceptionWithStack(process()->GetKoid(), thread()->GetKoid(),
                           debug_ipc::ExceptionType::kSingleStep,
                           MockFrameVectorToFrameVector(std::move(mock_frames)), true);
}

}  // namespace zxdb
