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

#include <gtest/gtest.h>

#include "llvm/BinaryFormat/Dwarf.h"
#include "src/developer/debug/zxdb/common/test_with_loop.h"
#include "src/developer/debug/zxdb/expr/mock_eval_context.h"
#include "src/developer/debug/zxdb/expr/test_eval_context_impl.h"
#include "src/developer/debug/zxdb/expr/virtual_base_test_setup.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/elf_symbol.h"
#include "src/developer/debug/zxdb/symbols/inherited_from.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/mock_module_symbols.h"
#include "src/developer/debug/zxdb/symbols/mock_symbol_data_provider.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/process_symbols_test_setup.h"
#include "src/developer/debug/zxdb/symbols/type_test_support.h"

namespace zxdb {

namespace {

class ResolveBase : public TestWithLoop {};

}  // namespace

// Given a class without a vtable, verifies that the DerivedTypeForVtable does a synchronous no-op.
TEST_F(ResolveBase, PromotePtrRefToDerived_NoVtable) {
  auto eval_context = fxl::MakeRefCounted<MockEvalContext>();

  auto not_virtual =
      MakeCollectionType(DwarfTag::kStructureType, "MyStruct", {{"a", MakeInt32Type()}});
  std::vector<uint8_t> data{42, 0, 0, 0};  // int32_t = 42.

  ExprValue value(not_virtual, data);

  bool called = false;
  PromotePtrRefToDerived(eval_context, PromoteToDerived::kPtrOrRef, value,
                         [&called, original_value = value](ErrOrValue result) {
                           called = true;
                           EXPECT_TRUE(result.ok());
                           EXPECT_EQ(original_value, result.value());

                           // In this test the type object pointers should be the same (not normally
                           // tested in value equality) since the value should be the same one just
                           // forwarded.
                           EXPECT_EQ(original_value.type(), result.value().type());
                         });
  EXPECT_TRUE(called);
}

TEST_F(ResolveBase, PromotePtrRefToDerived) {
  ProcessSymbolsTestSetup symbol_setup;
  MockModuleSymbols* mock_module_symbols = symbol_setup.InjectMockModule();
  SymbolContext symbol_context(ProcessSymbolsTestSetup::kDefaultLoadAddress);

  auto symbol_data_provider = fxl::MakeRefCounted<MockSymbolDataProvider>();
  auto eval_context = fxl::MakeRefCounted<TestEvalContextImpl>(
      symbol_setup.process().GetWeakPtr(), symbol_data_provider, ExprLanguage::kC);

  VirtualBaseTestSetup setup(symbol_data_provider.get(), mock_module_symbols);

  // Add a bunch of qualifiers to make sure they come out the other end.
  auto const_base_class = fxl::MakeRefCounted<ModifiedType>(DwarfTag::kConstType, setup.base_class);
  auto ptr_const_base_class =
      fxl::MakeRefCounted<ModifiedType>(DwarfTag::kPointerType, const_base_class);
  auto const_ptr_const_base_class =
      fxl::MakeRefCounted<ModifiedType>(DwarfTag::kConstType, ptr_const_base_class);

  // Input Base*.
  ExprValue base_ptr(setup.kBaseAddress, const_ptr_const_base_class);

  // -----------------------------------------------------------------------------------------------
  // Part 1: vtable pointer points to "Derived".

  // The default setup will have the vtable point to the derived class.
  ErrOrValue result(Err("Not called"));
  PromotePtrRefToDerived(eval_context, PromoteToDerived::kPtrOrRef, base_ptr,
                         [&result](ErrOrValue r) { result = r; });
  loop().RunUntilNoTasks();
  ASSERT_TRUE(result.ok());

  // Now that the memory has been hooked up, the result should be a const*const (consts copied from
  // the original base type) with the derived address.
  uint64_t result64 = 0;
  ASSERT_TRUE(result.value().PromoteTo64(&result64).ok());
  EXPECT_EQ(setup.kDerivedAddress, result64);
  EXPECT_EQ("const DerivedClass* const", result.value().type()->GetFullName());

  // -----------------------------------------------------------------------------------------------
  // Part 2: vtable pointer points to "Base".

  // Fix up the vtable pointer to the base class.
  Location vtable_location(setup.kVtableAbsoluteAddress, FileLine(), 0, symbol_context,
                           setup.base_vtable);
  mock_module_symbols->AddSymbolLocations(setup.kVtableAbsoluteAddress, {vtable_location});

  result = Err("Not called");
  PromotePtrRefToDerived(eval_context, PromoteToDerived::kPtrOrRef, base_ptr,
                         [&result](ErrOrValue r) { result = r; });
  loop().RunUntilNoTasks();
  ASSERT_TRUE(result.ok()) << result.err().msg();
  EXPECT_EQ(base_ptr, result.value());  // Should give same input as output.

  // -----------------------------------------------------------------------------------------------
  // Part 3: vtable pointer is invalid.

  // Declare no symbol at this address.
  mock_module_symbols->AddSymbolLocations(
      setup.kVtableAbsoluteAddress,
      {Location(Location::State::kSymbolized, setup.kVtableAbsoluteAddress)});

  // Should run asynchronously and produce success.
  result = Err("Not called");
  PromotePtrRefToDerived(eval_context, PromoteToDerived::kPtrOrRef, base_ptr,
                         [&result](ErrOrValue r) { result = r; });
  loop().RunUntilNoTasks();
  ASSERT_TRUE(result.ok());

  // We did not hook up the vtable memory above so the resolution will fail. It should fall back on
  // returning the input rather than forwarding an error.
  EXPECT_EQ(base_ptr, result.value());
  EXPECT_EQ("const BaseClass* const", result.value().type()->GetFullName());

  // -----------------------------------------------------------------------------------------------
  // Part 4: virtual inheritance means we can't promote to derived.

  // Put back the good derived vtable location cleared in the previous step so it will succeed.
  mock_module_symbols->AddSymbolLocations(setup.kVtableAbsoluteAddress,
                                          {Location(setup.kVtableAbsoluteAddress, FileLine(), 0,
                                                    symbol_context, setup.derived_vtable)});

  // Replace the inheritance record with one indicating virtual inheritance. This placeholder
  // expression won't work in practice (see VirtualInheritanceTestSetup for a real one) but the
  // presence of some expression will trigger a casting failure.
  auto virtual_inheritance = fxl::MakeRefCounted<InheritedFrom>(
      setup.base_class, std::vector<uint8_t>{llvm::dwarf::DW_OP_dup});
  setup.derived_class->set_inherited_from({LazySymbol(virtual_inheritance)});

  result = Err("Not called");
  PromotePtrRefToDerived(eval_context, PromoteToDerived::kPtrOrRef, base_ptr,
                         [&result](ErrOrValue r) { result = r; });
  loop().RunUntilNoTasks();
  ASSERT_TRUE(result.ok()) << result.err().msg();
  EXPECT_EQ(base_ptr, result.value());  // Should give same input as output.
}

}  // namespace zxdb
