/*
 * 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 "mirror/abstract_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "oat_file.h"
#include "oat_writer.h"
#include "vector_output_stream.h"

#include "common_test.h"

namespace art {

class OatTest : public CommonTest {
 protected:
  void CheckMethod(mirror::AbstractMethod* method,
                   const OatFile::OatMethod& oat_method,
                   const DexFile* dex_file)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    const CompiledMethod* compiled_method =
        compiler_driver_->GetCompiledMethod(CompilerDriver::MethodReference(dex_file,
                                                               method->GetDexMethodIndex()));

    if (compiled_method == NULL) {
      EXPECT_TRUE(oat_method.GetCode() == NULL) << PrettyMethod(method) << " "
                                                << oat_method.GetCode();
#if !defined(ART_USE_PORTABLE_COMPILER)
      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), static_cast<uint32_t>(kStackAlignment));
      EXPECT_EQ(oat_method.GetCoreSpillMask(), 0U);
      EXPECT_EQ(oat_method.GetFpSpillMask(), 0U);
#endif
    } else {
      const void* oat_code = oat_method.GetCode();
      EXPECT_TRUE(oat_code != NULL) << PrettyMethod(method);
      uintptr_t oat_code_aligned = RoundDown(reinterpret_cast<uintptr_t>(oat_code), 2);
      oat_code = reinterpret_cast<const void*>(oat_code_aligned);

      const std::vector<uint8_t>& code = compiled_method->GetCode();
      size_t code_size = code.size() * sizeof(code[0]);
      EXPECT_EQ(0, memcmp(oat_code, &code[0], code_size))
          << PrettyMethod(method) << " " << code_size;
      CHECK_EQ(0, memcmp(oat_code, &code[0], code_size));
#if !defined(ART_USE_PORTABLE_COMPILER)
      EXPECT_EQ(oat_method.GetFrameSizeInBytes(), compiled_method->GetFrameSizeInBytes());
      EXPECT_EQ(oat_method.GetCoreSpillMask(), compiled_method->GetCoreSpillMask());
      EXPECT_EQ(oat_method.GetFpSpillMask(), compiled_method->GetFpSpillMask());
#endif
    }
  }
};

TEST_F(OatTest, WriteRead) {
  const bool compile = false;  // DISABLED_ due to the time to compile libcore
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();

  jobject class_loader = NULL;
  if (compile) {
    // TODO: make selectable
#if defined(ART_USE_PORTABLE_COMPILER)
    CompilerBackend compiler_backend = kPortable;
#else
    CompilerBackend compiler_backend = kQuick;
#endif
    compiler_driver_.reset(new CompilerDriver(compiler_backend, kThumb2, false, 2, false, false,
                                              NULL, true, true));
    compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath());
  }

  ScopedObjectAccess soa(Thread::Current());
  ScratchFile tmp;
  std::vector<uint8_t> oat_contents;
  VectorOutputStream output_stream(tmp.GetFilename(), oat_contents);
  bool success_oat = OatWriter::Create(output_stream,
                                       class_linker->GetBootClassPath(),
                                       42U,
                                       4096U,
                                       "lue.art",
                                       *compiler_driver_.get());
  ASSERT_TRUE(success_oat);
  bool success_elf = compiler_driver_->WriteElf(GetTestAndroidRoot(),
                                                !kIsTargetBuild,
                                                class_linker->GetBootClassPath(),
                                                oat_contents,
                                                tmp.GetFile());
  ASSERT_TRUE(success_elf);

  if (compile) {  // OatWriter strips the code, regenerate to compare
    compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath());
  }
  UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL));
  ASSERT_TRUE(oat_file.get() != NULL);
  const OatHeader& oat_header = oat_file->GetOatHeader();
  ASSERT_TRUE(oat_header.IsValid());
  ASSERT_EQ(1U, oat_header.GetDexFileCount());
  ASSERT_EQ(42U, oat_header.GetImageFileLocationOatChecksum());
  ASSERT_EQ(4096U, oat_header.GetImageFileLocationOatDataBegin());
  ASSERT_EQ("lue.art", oat_header.GetImageFileLocation());

  const DexFile* dex_file = java_lang_dex_file_;
  const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file->GetLocation());
  CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum());
  for (size_t i = 0; i < dex_file->NumClassDefs(); i++) {
    const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
    const byte* class_data = dex_file->GetClassData(class_def);
    size_t num_virtual_methods =0;
    if (class_data != NULL) {
      ClassDataItemIterator it(*dex_file, class_data);
      num_virtual_methods = it.NumVirtualMethods();
    }
    const char* descriptor = dex_file->GetClassDescriptor(class_def);

    UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(i));

    mirror::Class* klass = class_linker->FindClass(descriptor, NULL);

    size_t method_index = 0;
    for (size_t i = 0; i < klass->NumDirectMethods(); i++, method_index++) {
      CheckMethod(klass->GetDirectMethod(i),
                  oat_class->GetOatMethod(method_index), dex_file);
    }
    for (size_t i = 0; i < num_virtual_methods; i++, method_index++) {
      CheckMethod(klass->GetVirtualMethod(i),
                  oat_class->GetOatMethod(method_index), dex_file);
    }
  }
}

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(36U, sizeof(OatHeader));
  EXPECT_EQ(28U, sizeof(OatMethodOffsets));
}

TEST_F(OatTest, OatHeaderIsValid) {
    InstructionSet instruction_set = kX86;
    std::vector<const DexFile*> dex_files;
    uint32_t image_file_location_oat_checksum = 0;
    uint32_t image_file_location_oat_begin = 0;
    const std::string image_file_location;
    OatHeader oat_header(instruction_set,
                         &dex_files,
                         image_file_location_oat_checksum,
                         image_file_location_oat_begin,
                         image_file_location);
    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());
}

}  // namespace art
