// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "riscv/riscv64_decoder.h"

#include <cstdint>
#include <string>

#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/log/log_sink_registry.h"
#include "absl/strings/str_cat.h"
#include "elfio/elf_types.hpp"
#include "elfio/elfio.hpp"
#include "elfio/elfio_section.hpp"
#include "elfio/elfio_symbols.hpp"
#include "googlemock/include/gmock/gmock.h"
#include "mpact/sim/generic/instruction.h"
#include "mpact/sim/util/memory/flat_demand_memory.h"
#include "mpact/sim/util/other/log_sink.h"
#include "mpact/sim/util/program_loader/elf_program_loader.h"
#include "riscv/riscv_state.h"

namespace {

using ::mpact::sim::riscv::RiscV64Decoder;
using ::mpact::sim::riscv::RiscVState;
using ::mpact::sim::riscv::RiscVXlen;
using ::mpact::sim::util::LogSink;

constexpr char kFileName[] = "hello_world_64.elf";

// The depot path to the test directory.
constexpr char kDepotPath[] = "riscv/test/";

using SymbolAccessor = ELFIO::symbol_section_accessor_template<ELFIO::section>;

class RiscV64DecoderTest : public testing::Test {
 protected:
  RiscV64DecoderTest()
      : state_("riscv64_test", RiscVXlen::RV64, &memory_),
        loader_(&memory_),
        decoder_(&state_, &memory_) {
    const std::string input_file =
        absl::StrCat(kDepotPath, "testfiles/", kFileName);
    auto result = loader_.LoadProgram(input_file);
    CHECK_OK(result.status());
    elf_reader_.load(input_file);
    auto *symtab = elf_reader_.sections[".symtab"];
    CHECK_NE(symtab, nullptr);
    symbol_accessor_ = new SymbolAccessor(elf_reader_, symtab);
  }

  ~RiscV64DecoderTest() override { delete symbol_accessor_; }

  ELFIO::elfio elf_reader_;
  RiscVState state_;
  mpact::sim::util::FlatDemandMemory memory_;
  mpact::sim::util::ElfProgramLoader loader_;
  RiscV64Decoder decoder_;
  SymbolAccessor *symbol_accessor_;
};

TEST_F(RiscV64DecoderTest, Getters) {
  RiscV64Decoder *decoder = nullptr;
  LogSink log_sink;
  absl::AddLogSink(&log_sink);
  decoder = new RiscV64Decoder(&state_, &memory_);
  EXPECT_EQ(log_sink.num_error(), 0);
  absl::RemoveLogSink(&log_sink);
  delete decoder;
}

// This test is really pretty simple. It decodes the instructions in "main".
// The goal of this test is not so much to ensure that the decoder is accurate,
// but that the decoder returns a non-null instruction object for each address
// in main, and that executing this instruction does not generate an error.
TEST_F(RiscV64DecoderTest, HelloWorldMain) {
  ELFIO::Elf64_Addr value;
  ELFIO::Elf_Xword size;
  unsigned char bind;
  unsigned char type;
  ELFIO::Elf_Half section_index;
  unsigned char other;
  bool success = symbol_accessor_->get_symbol("main", value, size, bind, type,
                                              section_index, other);
  ASSERT_TRUE(success);
  uint64_t address = value;
  while (address < value + size) {
    EXPECT_FALSE(state_.program_error_controller()->HasError());
    auto *inst = decoder_.DecodeInstruction(address);
    ASSERT_NE(inst, nullptr);
    inst->Execute(nullptr);
    if (state_.program_error_controller()->HasError()) {
      auto errvec = state_.program_error_controller()->GetUnmaskedErrorNames();
      for (auto &err : errvec) {
        LOG(INFO) << "Error: " << err;
        auto msgvec = state_.program_error_controller()->GetErrorMessages(err);
        for (auto &msg : msgvec) {
          LOG(INFO) << "    " << msg;
        }
      }
    }
    EXPECT_FALSE(state_.program_error_controller()->HasError());
    state_.program_error_controller()->ClearAll();
    address += inst->size();
    inst->DecRef();
    state_.AdvanceDelayLines();
  }
}

// Even with a bad address, a valid instruction object should be returned.
TEST_F(RiscV64DecoderTest, BadAddress) {
  auto *inst = decoder_.DecodeInstruction(0x4321);
  ASSERT_NE(inst, nullptr);
  inst->Execute(nullptr);
  inst->DecRef();
}

}  // namespace
