/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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
 *
 *      http://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.
 */

#ifndef ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_
#define ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_

#include <dirent.h>
#include <stdio.h>
#include <sys/types.h>

#include <cstring>
#include <memory>
#include <set>
#include <string>

#include "base/macros.h"
#include "base/os.h"
#include "base/unix_file/fd_file.h"
#include "common_compiler_test.h"
#include "elf/elf_builder.h"
#include "gtest/gtest.h"
#include "stream/file_output_stream.h"

namespace art HIDDEN {
namespace dwarf {

#define DW_CHECK(substring) Check(substring, false, __FILE__, __LINE__)
#define DW_CHECK_NEXT(substring) Check(substring, true, __FILE__, __LINE__)

class DwarfTest : public CommonCompilerTest {
 public:
  static constexpr bool kPrintObjdumpOutput = false;  // debugging.

  struct ExpectedLine {
    std::string substring;
    bool next;
    const char* at_file;
    int at_line;
  };

  // Check that the objdump output contains given output.
  // If next is true, it must be the next line.  Otherwise lines are skipped.
  void Check(const char* substr, bool next, const char* at_file, int at_line) {
    expected_lines_.push_back(ExpectedLine {substr, next, at_file, at_line});
  }

  // Pretty-print the generated DWARF data using objdump.
  template<typename ElfTypes>
  std::vector<std::string> Objdump(const char* args) {
    // Write simple elf file with just the DWARF sections.
    InstructionSet isa =
        (sizeof(typename ElfTypes::Addr) == 8) ? InstructionSet::kX86_64 : InstructionSet::kX86;
    ScratchFile file;
    FileOutputStream output_stream(file.GetFile());
    ElfBuilder<ElfTypes> builder(isa, &output_stream);
    builder.Start();
    if (!debug_info_data_.empty()) {
      builder.WriteSection(".debug_info", &debug_info_data_);
    }
    if (!debug_abbrev_data_.empty()) {
      builder.WriteSection(".debug_abbrev", &debug_abbrev_data_);
    }
    if (!debug_str_data_.empty()) {
      builder.WriteSection(".debug_str", &debug_str_data_);
    }
    if (!debug_line_data_.empty()) {
      builder.WriteSection(".debug_line", &debug_line_data_);
    }
    if (!debug_frame_data_.empty()) {
      builder.WriteSection(".debug_frame", &debug_frame_data_);
    }
    builder.End();
    EXPECT_TRUE(builder.Good());

    // Read the elf file back using objdump.
    std::vector<std::string> lines;
    std::string cmd = GetAndroidTool("llvm-dwarfdump");
    cmd = cmd + " " + args + " " + file.GetFilename() + " 2>&1";
    FILE* output = popen(cmd.data(), "r");
    char buffer[1024];
    const char* line;
    while ((line = fgets(buffer, sizeof(buffer), output)) != nullptr) {
      if (kPrintObjdumpOutput) {
        printf("%s", line);
      }
      if (line[0] != '\0' && line[0] != '\n') {
        EXPECT_TRUE(strstr(line, "error:") == nullptr) << line;
        EXPECT_TRUE(strstr(line, "warning:") == nullptr) << line;
        std::string str(line);
        if (str.back() == '\n') {
          str.pop_back();
        }
        std::replace(str.begin(), str.end(), '\t', ' ');
        lines.push_back(str);
      }
    }
    pclose(output);
    return lines;
  }

  std::vector<std::string> Objdump(bool is64bit, const char* args) {
    if (is64bit) {
      return Objdump<ElfTypes64>(args);
    } else {
      return Objdump<ElfTypes32>(args);
    }
  }

  // Compare objdump output to the recorded checks.
  void CheckObjdumpOutput(bool is64bit, const char* args) {
    std::vector<std::string> actual_lines = Objdump(is64bit, args);
    auto actual_line = actual_lines.begin();
    bool failed = false;
    for (const ExpectedLine& expected : expected_lines_) {
      const std::string& substring = expected.substring;
      auto it = std::find_if(actual_line, actual_lines.end(),
          [&](const std::string& line) { return line.find(substring) != std::string::npos; });
      if (it == actual_lines.end()) {
        failed = true;
        ADD_FAILURE_AT(expected.at_file, expected.at_line) << "'" << substring << "' not found.";
      } else {
        if (expected.next && it != actual_line) {
          failed = true;
          ADD_FAILURE_AT(expected.at_file, expected.at_line)
              << "'" << substring << "' found, but not on the immediate next line as expected.";
        }
        actual_line = ++it;
      }
    }
    if (failed) {
      LOG(ERROR) << "objdump output:";
      for (const std::string& it : actual_lines) {
        LOG(ERROR) << it;
      }
    }
  }

  // Buffers which are going to assembled into ELF file and passed to objdump.
  std::vector<uint8_t> debug_frame_data_;
  std::vector<uint8_t> debug_info_data_;
  std::vector<uint8_t> debug_abbrev_data_;
  std::vector<uint8_t> debug_str_data_;
  std::vector<uint8_t> debug_line_data_;

  // The expected output of objdump.
  std::vector<ExpectedLine> expected_lines_;
};

}  // namespace dwarf
}  // namespace art

#endif  // ART_COMPILER_DEBUG_DWARF_DWARF_TEST_H_
