/*
 * Copyright (C) 2011 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.
 */

#include "android-base/stringprintf.h"

#include "arch/instruction_set_features.h"
#include "art_method-inl.h"
#include "base/file_utils.h"
#include "base/pointer_size.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "common_compiler_driver_test.h"
#include "compiler.h"
#include "debug/method_debug_info.h"
#include "dex/class_accessor-inl.h"
#include "dex/dex_file_loader.h"
#include "dex/quick_compiler_callbacks.h"
#include "dex/test_dex_file_builder.h"
#include "dex/verification_results.h"
#include "driver/compiled_method-inl.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "linker/elf_writer.h"
#include "linker/elf_writer_quick.h"
#include "linker/multi_oat_relative_patcher.h"
#include "mirror/class-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "oat/oat.h"
#include "oat/oat_file-inl.h"
#include "oat_writer.h"
#include "profile/profile_compilation_info.h"
#include "scoped_thread_state_change-inl.h"
#include "stream/buffered_output_stream.h"
#include "stream/file_output_stream.h"
#include "stream/vector_output_stream.h"
#include "vdex_file.h"

namespace art {
namespace linker {

class OatTest : public CommonCompilerDriverTest {
 protected:
  static const bool kCompile = false;  // DISABLED_ due to the time to compile libcore

  void CheckMethod(ArtMethod* method,
                   const OatFile::OatMethod& oat_method,
                   const DexFile& dex_file)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    const CompiledMethod* compiled_method =
        compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
                                                            method->GetDexMethodIndex()));

    if (compiled_method == nullptr) {
      EXPECT_TRUE(oat_method.GetQuickCode() == nullptr) << method->PrettyMethod() << " "
                                                        << oat_method.GetQuickCode();
      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), 0U);
      EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
      EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
    } else {
      const void* quick_oat_code = oat_method.GetQuickCode();
      EXPECT_TRUE(quick_oat_code != nullptr) << method->PrettyMethod();
      uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(quick_oat_code), 2);
      quick_oat_code = reinterpret_cast<const void*>(oat_code_aligned);
      ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
      EXPECT_FALSE(quick_code.empty());
      size_t code_size = quick_code.size() * sizeof(quick_code[0]);
      EXPECT_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size))
          << method->PrettyMethod() << " " << code_size;
      CHECK_EQ(0, memcmp(quick_oat_code, &quick_code[0], code_size));
    }
  }

  void SetupCompiler(const std::vector<std::string>& compiler_options) {
    std::string error_msg;
    if (!compiler_options_->ParseCompilerOptions(compiler_options,
                                                 /*ignore_unrecognized=*/ false,
                                                 &error_msg)) {
      LOG(FATAL) << error_msg;
      UNREACHABLE();
    }
    callbacks_.reset(new QuickCompilerCallbacks(CompilerCallbacks::CallbackMode::kCompileApp));
    callbacks_->SetVerificationResults(verification_results_.get());
    Runtime::Current()->SetCompilerCallbacks(callbacks_.get());
  }

  bool WriteElf(File* vdex_file,
                File* oat_file,
                const std::vector<const DexFile*>& dex_files,
                SafeMap<std::string, std::string>& key_value_store,
                bool verify) {
    TimingLogger timings("WriteElf", false, false);
    ClearBootImageOption();
    OatWriter oat_writer(*compiler_options_,
                         verification_results_.get(),
                         &timings,
                         /*profile_compilation_info*/nullptr,
                         CompactDexLevel::kCompactDexLevelNone);
    for (const DexFile* dex_file : dex_files) {
      if (!oat_writer.AddRawDexFileSource(dex_file->GetContainer(),
                                          dex_file->Begin(),
                                          dex_file->GetLocation().c_str(),
                                          dex_file->GetLocationChecksum())) {
        return false;
      }
    }
    return DoWriteElf(
        vdex_file, oat_file, oat_writer, key_value_store, verify, CopyOption::kOnlyIfCompressed);
  }

  bool WriteElf(File* vdex_file,
                File* oat_file,
                const std::vector<const char*>& dex_filenames,
                SafeMap<std::string, std::string>& key_value_store,
                bool verify,
                CopyOption copy,
                ProfileCompilationInfo* profile_compilation_info) {
    TimingLogger timings("WriteElf", false, false);
    ClearBootImageOption();
    OatWriter oat_writer(*compiler_options_,
                         verification_results_.get(),
                         &timings,
                         profile_compilation_info,
                         CompactDexLevel::kCompactDexLevelNone);
    for (const char* dex_filename : dex_filenames) {
      if (!oat_writer.AddDexFileSource(dex_filename, dex_filename)) {
        return false;
      }
    }
    return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify, copy);
  }

  bool WriteElf(File* vdex_file,
                File* oat_file,
                File&& dex_file_fd,
                const char* location,
                SafeMap<std::string, std::string>& key_value_store,
                bool verify,
                CopyOption copy,
                ProfileCompilationInfo* profile_compilation_info = nullptr) {
    TimingLogger timings("WriteElf", false, false);
    ClearBootImageOption();
    OatWriter oat_writer(*compiler_options_,
                         verification_results_.get(),
                         &timings,
                         profile_compilation_info,
                         CompactDexLevel::kCompactDexLevelNone);
    if (!oat_writer.AddDexFileSource(std::move(dex_file_fd), location)) {
      return false;
    }
    return DoWriteElf(vdex_file, oat_file, oat_writer, key_value_store, verify, copy);
  }

  bool DoWriteElf(File* vdex_file,
                  File* oat_file,
                  OatWriter& oat_writer,
                  SafeMap<std::string, std::string>& key_value_store,
                  bool verify,
                  CopyOption copy) {
    std::unique_ptr<ElfWriter> elf_writer = CreateElfWriterQuick(
        compiler_driver_->GetCompilerOptions(),
        oat_file);
    elf_writer->Start();
    OutputStream* oat_rodata = elf_writer->StartRoData();
    std::vector<MemMap> opened_dex_files_maps;
    std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
    if (!oat_writer.WriteAndOpenDexFiles(
        vdex_file,
        verify,
        /*use_existing_vdex=*/ false,
        copy,
        &opened_dex_files_maps,
        &opened_dex_files)) {
      return false;
    }

    Runtime* runtime = Runtime::Current();
    ClassLinker* const class_linker = runtime->GetClassLinker();
    std::vector<const DexFile*> dex_files;
    for (const std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
      dex_files.push_back(dex_file.get());
      ScopedObjectAccess soa(Thread::Current());
      class_linker->RegisterDexFile(*dex_file, nullptr);
    }
    MultiOatRelativePatcher patcher(compiler_options_->GetInstructionSet(),
                                    compiler_options_->GetInstructionSetFeatures(),
                                    compiler_driver_->GetCompiledMethodStorage());
    if (!oat_writer.StartRoData(dex_files, oat_rodata, &key_value_store)) {
      return false;
    }
    oat_writer.Initialize(compiler_driver_.get(), /*image_writer=*/ nullptr, dex_files);
    if (!oat_writer.FinishVdexFile(vdex_file, /*verifier_deps=*/ nullptr)) {
      return false;
    }
    oat_writer.PrepareLayout(&patcher);
    elf_writer->PrepareDynamicSection(oat_writer.GetOatHeader().GetExecutableOffset(),
                                      oat_writer.GetCodeSize(),
                                      oat_writer.GetDataImgRelRoSize(),
                                      oat_writer.GetBssSize(),
                                      oat_writer.GetBssMethodsOffset(),
                                      oat_writer.GetBssRootsOffset(),
                                      oat_writer.GetVdexSize());


    if (!oat_writer.WriteRodata(oat_rodata)) {
      return false;
    }
    elf_writer->EndRoData(oat_rodata);

    OutputStream* text = elf_writer->StartText();
    if (!oat_writer.WriteCode(text)) {
      return false;
    }
    elf_writer->EndText(text);

    if (oat_writer.GetDataImgRelRoSize() != 0u) {
      OutputStream* data_img_rel_ro = elf_writer->StartDataImgRelRo();
      if (!oat_writer.WriteDataImgRelRo(data_img_rel_ro)) {
        return false;
      }
      elf_writer->EndDataImgRelRo(data_img_rel_ro);
    }

    if (!oat_writer.WriteHeader(elf_writer->GetStream())) {
      return false;
    }

    elf_writer->WriteDynamicSection();
    elf_writer->WriteDebugInfo(oat_writer.GetDebugInfo());

    if (!elf_writer->End()) {
      return false;
    }

    for (MemMap& map : opened_dex_files_maps) {
      opened_dex_files_maps_.emplace_back(std::move(map));
    }
    for (std::unique_ptr<const DexFile>& dex_file : opened_dex_files) {
      opened_dex_files_.emplace_back(dex_file.release());
    }
    return true;
  }

  void CheckOatWriteResult(ScratchFile& oat_file,
                           ScratchFile& vdex_file,
                           std::vector<std::unique_ptr<const DexFile>>& input_dexfiles,
                           const unsigned int expected_oat_dexfile_count,
                           bool low_4gb) {
    ASSERT_EQ(expected_oat_dexfile_count, input_dexfiles.size());

    std::string error_msg;
    std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                           oat_file.GetFilename(),
                                                           oat_file.GetFilename(),
                                                           /*executable=*/ false,
                                                           low_4gb,
                                                           &error_msg));
    ASSERT_TRUE(opened_oat_file != nullptr) << error_msg;
    ASSERT_EQ(expected_oat_dexfile_count, opened_oat_file->GetOatDexFiles().size());

    if (low_4gb) {
      uintptr_t begin = reinterpret_cast<uintptr_t>(opened_oat_file->Begin());
      EXPECT_EQ(begin, static_cast<uint32_t>(begin));
    }

    for (uint32_t i = 0; i <  input_dexfiles.size(); i++) {
      const std::unique_ptr<const DexFile>& dex_file_data = input_dexfiles[i];
      std::unique_ptr<const DexFile> opened_dex_file =
          opened_oat_file->GetOatDexFiles()[i]->OpenDexFile(&error_msg);

      ASSERT_EQ(opened_oat_file->GetOatDexFiles()[i]->GetDexFileLocationChecksum(),
                dex_file_data->GetHeader().checksum_);

      ASSERT_EQ(dex_file_data->GetHeader().file_size_, opened_dex_file->GetHeader().file_size_);
      ASSERT_EQ(0, memcmp(&dex_file_data->GetHeader(),
                          &opened_dex_file->GetHeader(),
                          dex_file_data->GetHeader().file_size_));
      ASSERT_EQ(dex_file_data->GetLocation(), opened_dex_file->GetLocation());
    }

    int64_t actual_vdex_size = vdex_file.GetFile()->GetLength();
    ASSERT_GE(actual_vdex_size, 0);
    ASSERT_EQ(dchecked_integral_cast<uint64_t>(actual_vdex_size),
              opened_oat_file->GetVdexFile()->GetComputedFileSize());
  }

  void TestDexFileInput(bool verify, bool low_4gb, bool use_profile);
  void TestZipFileInput(bool verify, CopyOption copy);
  void TestZipFileInputWithEmptyDex();

  std::unique_ptr<QuickCompilerCallbacks> callbacks_;

  std::vector<MemMap> opened_dex_files_maps_;
  std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
};

class ZipBuilder {
 public:
  explicit ZipBuilder(File* zip_file) : zip_file_(zip_file) { }

  bool AddFile(const char* location, const void* data, size_t size) {
    off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR);
    if (offset == static_cast<off_t>(-1)) {
      return false;
    }

    ZipFileHeader file_header;
    file_header.crc32 = crc32(0u, reinterpret_cast<const Bytef*>(data), size);
    file_header.compressed_size = size;
    file_header.uncompressed_size = size;
    file_header.filename_length = strlen(location);

    if (!zip_file_->WriteFully(&file_header, sizeof(file_header)) ||
        !zip_file_->WriteFully(location, file_header.filename_length) ||
        !zip_file_->WriteFully(data, size)) {
      return false;
    }

    CentralDirectoryFileHeader cdfh;
    cdfh.crc32 = file_header.crc32;
    cdfh.compressed_size = size;
    cdfh.uncompressed_size = size;
    cdfh.filename_length = file_header.filename_length;
    cdfh.relative_offset_of_local_file_header = offset;
    file_data_.push_back(FileData { cdfh, location });
    return true;
  }

  bool Finish() {
    off_t offset = lseek(zip_file_->Fd(), 0, SEEK_CUR);
    if (offset == static_cast<off_t>(-1)) {
      return false;
    }

    size_t central_directory_size = 0u;
    for (const FileData& file_data : file_data_) {
      if (!zip_file_->WriteFully(&file_data.cdfh, sizeof(file_data.cdfh)) ||
          !zip_file_->WriteFully(file_data.location, file_data.cdfh.filename_length)) {
        return false;
      }
      central_directory_size += sizeof(file_data.cdfh) + file_data.cdfh.filename_length;
    }
    EndOfCentralDirectoryRecord eocd_record;
    eocd_record.number_of_central_directory_records_on_this_disk = file_data_.size();
    eocd_record.total_number_of_central_directory_records = file_data_.size();
    eocd_record.size_of_central_directory = central_directory_size;
    eocd_record.offset_of_start_of_central_directory = offset;
    return
        zip_file_->WriteFully(&eocd_record, sizeof(eocd_record)) &&
        zip_file_->Flush() == 0;
  }

 private:
  struct PACKED(1) ZipFileHeader {
    uint32_t signature = 0x04034b50;
    uint16_t version_needed_to_extract = 10;
    uint16_t general_purpose_bit_flag = 0;
    uint16_t compression_method = 0;            // 0 = store only.
    uint16_t file_last_modification_time = 0u;
    uint16_t file_last_modification_date = 0u;
    uint32_t crc32;
    uint32_t compressed_size;
    uint32_t uncompressed_size;
    uint16_t filename_length;
    uint16_t extra_field_length = 0u;           // No extra fields.
  };

  struct PACKED(1) CentralDirectoryFileHeader {
    uint32_t signature = 0x02014b50;
    uint16_t version_made_by = 10;
    uint16_t version_needed_to_extract = 10;
    uint16_t general_purpose_bit_flag = 0;
    uint16_t compression_method = 0;            // 0 = store only.
    uint16_t file_last_modification_time = 0u;
    uint16_t file_last_modification_date = 0u;
    uint32_t crc32;
    uint32_t compressed_size;
    uint32_t uncompressed_size;
    uint16_t filename_length;
    uint16_t extra_field_length = 0u;           // No extra fields.
    uint16_t file_comment_length = 0u;          // No file comment.
    uint16_t disk_number_where_file_starts = 0u;
    uint16_t internal_file_attributes = 0u;
    uint32_t external_file_attributes = 0u;
    uint32_t relative_offset_of_local_file_header;
  };

  struct PACKED(1) EndOfCentralDirectoryRecord {
    uint32_t signature = 0x06054b50;
    uint16_t number_of_this_disk = 0u;
    uint16_t disk_where_central_directory_starts = 0u;
    uint16_t number_of_central_directory_records_on_this_disk;
    uint16_t total_number_of_central_directory_records;
    uint32_t size_of_central_directory;
    uint32_t offset_of_start_of_central_directory;
    uint16_t comment_length = 0u;               // No file comment.
  };

  struct FileData {
    CentralDirectoryFileHeader cdfh;
    const char* location;
  };

  File* zip_file_;
  std::vector<FileData> file_data_;
};

TEST_F(OatTest, WriteRead) {
  TimingLogger timings("OatTest::WriteRead", false, false);
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();

  std::string error_msg;
  SetupCompiler(std::vector<std::string>());

  jobject class_loader = nullptr;
  if (kCompile) {
    TimingLogger timings2("OatTest::WriteRead", false, false);
    CompileAll(class_loader, class_linker->GetBootClassPath(), &timings2);
  }

  ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
  SafeMap<std::string, std::string> key_value_store;
  key_value_store.Put(OatHeader::kBootClassPathChecksumsKey, "testkey");
  bool success = WriteElf(tmp_vdex.GetFile(),
                          tmp_oat.GetFile(),
                          class_linker->GetBootClassPath(),
                          key_value_store,
                          false);
  ASSERT_TRUE(success);

  if (kCompile) {  // OatWriter strips the code, regenerate to compare
    CompileAll(class_loader, class_linker->GetBootClassPath(), &timings);
  }
  std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                  tmp_oat.GetFilename(),
                                                  tmp_oat.GetFilename(),
                                                  /*executable=*/ false,
                                                  /*low_4gb=*/ true,
                                                  &error_msg));
  ASSERT_TRUE(oat_file.get() != nullptr) << error_msg;
  const OatHeader& oat_header = oat_file->GetOatHeader();
  ASSERT_TRUE(oat_header.IsValid());
  ASSERT_EQ(class_linker->GetBootClassPath().size(), oat_header.GetDexFileCount());  // core
  ASSERT_TRUE(oat_header.GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey) != nullptr);
  ASSERT_STREQ("testkey", oat_header.GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey));

  ASSERT_TRUE(java_lang_dex_file_ != nullptr);
  const DexFile& dex_file = *java_lang_dex_file_;
  const OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str());
  ASSERT_TRUE(oat_dex_file != nullptr);
  CHECK_EQ(dex_file.GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
  ScopedObjectAccess soa(Thread::Current());
  auto pointer_size = class_linker->GetImagePointerSize();
  for (ClassAccessor accessor : dex_file.GetClasses()) {
    size_t num_virtual_methods = accessor.NumVirtualMethods();

    const char* descriptor = accessor.GetDescriptor();
    ObjPtr<mirror::Class> klass = class_linker->FindClass(soa.Self(),
                                                          descriptor,
                                                          ScopedNullHandle<mirror::ClassLoader>());

    const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(accessor.GetClassDefIndex());
    CHECK_EQ(ClassStatus::kNotReady, oat_class.GetStatus()) << descriptor;
    CHECK_EQ(kCompile ? OatClassType::kAllCompiled : OatClassType::kNoneCompiled,
             oat_class.GetType()) << descriptor;

    size_t method_index = 0;
    for (auto& m : klass->GetDirectMethods(pointer_size)) {
      CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
      ++method_index;
    }
    size_t visited_virtuals = 0;
    // TODO We should also check copied methods in this test.
    for (auto& m : klass->GetDeclaredVirtualMethods(pointer_size)) {
      if (!klass->IsInterface()) {
        EXPECT_FALSE(m.IsCopied());
      }
      CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
      ++method_index;
      ++visited_virtuals;
    }
    EXPECT_EQ(visited_virtuals, num_virtual_methods);
  }
}

TEST_F(OatTest, OatHeaderSizeCheck) {
  // If this test is failing and you have to update these constants,
  // it is time to update OatHeader::kOatVersion
  EXPECT_EQ(68U, sizeof(OatHeader));
  EXPECT_EQ(4U, sizeof(OatMethodOffsets));
  EXPECT_EQ(4U, sizeof(OatQuickMethodHeader));
  EXPECT_EQ(170 * static_cast<size_t>(GetInstructionSetPointerSize(kRuntimeISA)),
            sizeof(QuickEntryPoints));
}

TEST_F(OatTest, OatHeaderIsValid) {
  InstructionSet insn_set = InstructionSet::kX86;
  std::string error_msg;
  std::unique_ptr<const InstructionSetFeatures> insn_features(
    InstructionSetFeatures::FromVariant(insn_set, "default", &error_msg));
  ASSERT_TRUE(insn_features.get() != nullptr) << error_msg;
  std::unique_ptr<OatHeader> oat_header(OatHeader::Create(insn_set,
                                                          insn_features.get(),
                                                          0u,
                                                          nullptr));
  ASSERT_NE(oat_header.get(), nullptr);
  ASSERT_TRUE(oat_header->IsValid());

  char* magic = const_cast<char*>(oat_header->GetMagic());
  strcpy(magic, "");  // bad magic
  ASSERT_FALSE(oat_header->IsValid());
  strcpy(magic, "oat\n000");  // bad version
  ASSERT_FALSE(oat_header->IsValid());
}

TEST_F(OatTest, EmptyTextSection) {
  TimingLogger timings("OatTest::EmptyTextSection", false, false);

  std::vector<std::string> compiler_options;
  compiler_options.push_back("--compiler-filter=extract");
  SetupCompiler(compiler_options);

  jobject class_loader;
  {
    ScopedObjectAccess soa(Thread::Current());
    class_loader = LoadDex("Main");
  }
  ASSERT_TRUE(class_loader != nullptr);
  std::vector<const DexFile*> dex_files = GetDexFiles(class_loader);
  ASSERT_TRUE(!dex_files.empty());

  ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
  for (const DexFile* dex_file : dex_files) {
    ScopedObjectAccess soa(Thread::Current());
    class_linker->RegisterDexFile(*dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
  }
  CompileAll(class_loader, dex_files, &timings);

  ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
  SafeMap<std::string, std::string> key_value_store;
  bool success = WriteElf(tmp_vdex.GetFile(),
                          tmp_oat.GetFile(),
                          dex_files,
                          key_value_store,
                          /*verify=*/ false);
  ASSERT_TRUE(success);

  std::string error_msg;
  std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                  tmp_oat.GetFilename(),
                                                  tmp_oat.GetFilename(),
                                                  /*executable=*/ false,
                                                  /*low_4gb=*/ false,
                                                  &error_msg));
  ASSERT_TRUE(oat_file != nullptr);
  EXPECT_LT(static_cast<size_t>(oat_file->Size()),
            static_cast<size_t>(tmp_oat.GetFile()->GetLength()));
}

static void MaybeModifyDexFileToFail(bool verify, std::unique_ptr<const DexFile>& data) {
  // If in verify mode (= fail the verifier mode), make sure we fail early. We'll fail already
  // because of the missing map, but that may lead to out of bounds reads.
  if (verify) {
    const_cast<DexFile::Header*>(&data->GetHeader())->checksum_++;
  }
}

void OatTest::TestDexFileInput(bool verify, bool low_4gb, bool use_profile) {
  TimingLogger timings("OatTest::DexFileInput", false, false);

  std::vector<const char*> input_filenames;
  std::vector<std::unique_ptr<const DexFile>> input_dexfiles;
  std::vector<const ScratchFile*> scratch_files;

  ScratchFile dex_file1;
  TestDexFileBuilder builder1;
  builder1.AddField("Lsome/TestClass;", "int", "someField");
  builder1.AddMethod("Lsome/TestClass;", "()I", "foo");
  std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());

  MaybeModifyDexFileToFail(verify, dex_file1_data);

  bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(),
                                                 dex_file1_data->GetHeader().file_size_);
  ASSERT_TRUE(success);
  success = dex_file1.GetFile()->Flush() == 0;
  ASSERT_TRUE(success);
  input_filenames.push_back(dex_file1.GetFilename().c_str());
  input_dexfiles.push_back(std::move(dex_file1_data));
  scratch_files.push_back(&dex_file1);

  ScratchFile dex_file2;
  TestDexFileBuilder builder2;
  builder2.AddField("Land/AnotherTestClass;", "boolean", "someOtherField");
  builder2.AddMethod("Land/AnotherTestClass;", "()J", "bar");
  std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());

  MaybeModifyDexFileToFail(verify, dex_file2_data);

  success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(),
                                            dex_file2_data->GetHeader().file_size_);
  ASSERT_TRUE(success);
  success = dex_file2.GetFile()->Flush() == 0;
  ASSERT_TRUE(success);
  input_filenames.push_back(dex_file2.GetFilename().c_str());
  input_dexfiles.push_back(std::move(dex_file2_data));
  scratch_files.push_back(&dex_file2);

  SafeMap<std::string, std::string> key_value_store;
  {
    // Test using the AddDexFileSource() interface with the dex files.
    ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
    std::unique_ptr<ProfileCompilationInfo>
        profile_compilation_info(use_profile ? new ProfileCompilationInfo() : nullptr);
    success = WriteElf(tmp_vdex.GetFile(),
                       tmp_oat.GetFile(),
                       input_filenames,
                       key_value_store,
                       verify,
                       CopyOption::kOnlyIfCompressed,
                       profile_compilation_info.get());

    // In verify mode, we expect failure.
    if (verify) {
      ASSERT_FALSE(success);
      return;
    }

    ASSERT_TRUE(success);

    CheckOatWriteResult(tmp_oat,
                        tmp_vdex,
                        input_dexfiles,
                        /* oat_dexfile_count */ 2,
                        low_4gb);
  }

  {
    // Test using the AddDexFileSource() interface with the dexfile1's fd.
    // Only need one input dexfile.
    std::vector<std::unique_ptr<const DexFile>> input_dexfiles2;
    input_dexfiles2.push_back(std::move(input_dexfiles[0]));
    const ScratchFile* dex_file = scratch_files[0];
    File dex_file_fd(DupCloexec(dex_file->GetFd()), /*check_usage=*/ false);

    ASSERT_NE(-1, dex_file_fd.Fd());
    ASSERT_EQ(0, lseek(dex_file_fd.Fd(), 0, SEEK_SET));

    ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
    std::unique_ptr<ProfileCompilationInfo>
        profile_compilation_info(use_profile ? new ProfileCompilationInfo() : nullptr);
    success = WriteElf(tmp_vdex.GetFile(),
                       tmp_oat.GetFile(),
                       std::move(dex_file_fd),
                       dex_file->GetFilename().c_str(),
                       key_value_store,
                       verify,
                       CopyOption::kOnlyIfCompressed,
                       profile_compilation_info.get());

    // In verify mode, we expect failure.
    if (verify) {
      ASSERT_FALSE(success);
      return;
    }

    ASSERT_TRUE(success);

    CheckOatWriteResult(tmp_oat,
                        tmp_vdex,
                        input_dexfiles2,
                        /* oat_dexfile_count */ 1,
                        low_4gb);
  }
}

TEST_F(OatTest, DexFileInputCheckOutput) {
  TestDexFileInput(/*verify*/false, /*low_4gb*/false, /*use_profile*/false);
}

TEST_F(OatTest, DexFileInputCheckOutputLow4GB) {
  TestDexFileInput(/*verify*/false, /*low_4gb*/true, /*use_profile*/false);
}

TEST_F(OatTest, DexFileInputCheckVerifier) {
  TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/false);
}

TEST_F(OatTest, DexFileFailsVerifierWithLayout) {
  TestDexFileInput(/*verify*/true, /*low_4gb*/false, /*use_profile*/true);
}

void OatTest::TestZipFileInput(bool verify, CopyOption copy) {
  TimingLogger timings("OatTest::DexFileInput", false, false);

  ScratchFile zip_file;
  ZipBuilder zip_builder(zip_file.GetFile());

  ScratchFile dex_file1;
  TestDexFileBuilder builder1;
  builder1.AddField("Lsome/TestClass;", "long", "someField");
  builder1.AddMethod("Lsome/TestClass;", "()D", "foo");
  std::unique_ptr<const DexFile> dex_file1_data = builder1.Build(dex_file1.GetFilename());

  MaybeModifyDexFileToFail(verify, dex_file1_data);

  bool success = dex_file1.GetFile()->WriteFully(&dex_file1_data->GetHeader(),
                                                 dex_file1_data->GetHeader().file_size_);
  ASSERT_TRUE(success);
  success = dex_file1.GetFile()->Flush() == 0;
  ASSERT_TRUE(success);
  success = zip_builder.AddFile("classes.dex",
                                &dex_file1_data->GetHeader(),
                                dex_file1_data->GetHeader().file_size_);
  ASSERT_TRUE(success);

  ScratchFile dex_file2;
  TestDexFileBuilder builder2;
  builder2.AddField("Land/AnotherTestClass;", "boolean", "someOtherField");
  builder2.AddMethod("Land/AnotherTestClass;", "()J", "bar");
  std::unique_ptr<const DexFile> dex_file2_data = builder2.Build(dex_file2.GetFilename());

  MaybeModifyDexFileToFail(verify, dex_file2_data);

  success = dex_file2.GetFile()->WriteFully(&dex_file2_data->GetHeader(),
                                            dex_file2_data->GetHeader().file_size_);
  ASSERT_TRUE(success);
  success = dex_file2.GetFile()->Flush() == 0;
  ASSERT_TRUE(success);
  success = zip_builder.AddFile("classes2.dex",
                                &dex_file2_data->GetHeader(),
                                dex_file2_data->GetHeader().file_size_);
  ASSERT_TRUE(success);

  success = zip_builder.Finish();
  ASSERT_TRUE(success) << strerror(errno);

  SafeMap<std::string, std::string> key_value_store;
  {
    // Test using the AddDexFileSource() interface with the zip file.
    std::vector<const char*> input_filenames = { zip_file.GetFilename().c_str() };

    ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
    success = WriteElf(tmp_vdex.GetFile(),
                       tmp_oat.GetFile(),
                       input_filenames,
                       key_value_store,
                       verify,
                       copy,
                       /*profile_compilation_info=*/ nullptr);

    if (verify) {
      ASSERT_FALSE(success);
    } else {
      ASSERT_TRUE(success);

      std::string error_msg;
      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                             tmp_oat.GetFilename(),
                                                             tmp_oat.GetFilename(),
                                                             /*executable=*/ false,
                                                             /*low_4gb=*/ false,
                                                             &error_msg));
      ASSERT_TRUE(opened_oat_file != nullptr) << error_msg;
      ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
      std::unique_ptr<const DexFile> opened_dex_file1 =
          opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
      std::unique_ptr<const DexFile> opened_dex_file2 =
          opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);

      ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
      ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
                          &opened_dex_file1->GetHeader(),
                          dex_file1_data->GetHeader().file_size_));
      ASSERT_EQ(DexFileLoader::GetMultiDexLocation(0, zip_file.GetFilename().c_str()),
                opened_dex_file1->GetLocation());

      ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
      ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
                          &opened_dex_file2->GetHeader(),
                          dex_file2_data->GetHeader().file_size_));
      ASSERT_EQ(DexFileLoader::GetMultiDexLocation(1, zip_file.GetFilename().c_str()),
                opened_dex_file2->GetLocation());
    }
  }

  {
    // Test using the AddDexFileSource() interface with the zip file handle.
    File zip_fd(DupCloexec(zip_file.GetFd()), /*check_usage=*/ false);
    ASSERT_NE(-1, zip_fd.Fd());
    ASSERT_EQ(0, lseek(zip_fd.Fd(), 0, SEEK_SET));

    ScratchFile tmp_base, tmp_oat(tmp_base, ".oat"), tmp_vdex(tmp_base, ".vdex");
    success = WriteElf(tmp_vdex.GetFile(),
                       tmp_oat.GetFile(),
                       std::move(zip_fd),
                       zip_file.GetFilename().c_str(),
                       key_value_store,
                       verify,
                       copy);
    if (verify) {
      ASSERT_FALSE(success);
    } else {
      ASSERT_TRUE(success);

      std::string error_msg;
      std::unique_ptr<OatFile> opened_oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                             tmp_oat.GetFilename(),
                                                             tmp_oat.GetFilename(),
                                                             /*executable=*/ false,
                                                             /*low_4gb=*/ false,
                                                             &error_msg));
      ASSERT_TRUE(opened_oat_file != nullptr) << error_msg;
      ASSERT_EQ(2u, opened_oat_file->GetOatDexFiles().size());
      std::unique_ptr<const DexFile> opened_dex_file1 =
          opened_oat_file->GetOatDexFiles()[0]->OpenDexFile(&error_msg);
      std::unique_ptr<const DexFile> opened_dex_file2 =
          opened_oat_file->GetOatDexFiles()[1]->OpenDexFile(&error_msg);

      ASSERT_EQ(dex_file1_data->GetHeader().file_size_, opened_dex_file1->GetHeader().file_size_);
      ASSERT_EQ(0, memcmp(&dex_file1_data->GetHeader(),
                          &opened_dex_file1->GetHeader(),
                          dex_file1_data->GetHeader().file_size_));
      ASSERT_EQ(DexFileLoader::GetMultiDexLocation(0, zip_file.GetFilename().c_str()),
                opened_dex_file1->GetLocation());

      ASSERT_EQ(dex_file2_data->GetHeader().file_size_, opened_dex_file2->GetHeader().file_size_);
      ASSERT_EQ(0, memcmp(&dex_file2_data->GetHeader(),
                          &opened_dex_file2->GetHeader(),
                          dex_file2_data->GetHeader().file_size_));
      ASSERT_EQ(DexFileLoader::GetMultiDexLocation(1, zip_file.GetFilename().c_str()),
                opened_dex_file2->GetLocation());
    }
  }
}

TEST_F(OatTest, ZipFileInputCheckOutput) {
  TestZipFileInput(false, CopyOption::kOnlyIfCompressed);
}

TEST_F(OatTest, ZipFileInputCheckOutputWithoutCopy) {
  TestZipFileInput(false, CopyOption::kNever);
}

TEST_F(OatTest, ZipFileInputCheckVerifier) {
  TestZipFileInput(true, CopyOption::kOnlyIfCompressed);
}

void OatTest::TestZipFileInputWithEmptyDex() {
  ScratchFile zip_file;
  ZipBuilder zip_builder(zip_file.GetFile());
  bool success = zip_builder.AddFile("classes.dex", nullptr, 0);
  ASSERT_TRUE(success);
  success = zip_builder.Finish();
  ASSERT_TRUE(success) << strerror(errno);

  SafeMap<std::string, std::string> key_value_store;
  std::vector<const char*> input_filenames = { zip_file.GetFilename().c_str() };
  ScratchFile oat_file, vdex_file(oat_file, ".vdex");
  std::unique_ptr<ProfileCompilationInfo> profile_compilation_info(new ProfileCompilationInfo());
  success = WriteElf(vdex_file.GetFile(),
                     oat_file.GetFile(),
                     input_filenames,
                     key_value_store,
                     /*verify=*/ false,
                     CopyOption::kOnlyIfCompressed,
                     profile_compilation_info.get());
  ASSERT_FALSE(success);
}

TEST_F(OatTest, ZipFileInputWithEmptyDex) {
  TestZipFileInputWithEmptyDex();
}

}  // namespace linker
}  // namespace art
