/*
 * 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 <string.h>
#include <vector>

#include "image_test.h"

#include "base/pointer_size.h"
#include "oat/image.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"

namespace art {
namespace linker {

TEST_F(ImageTest, TestImageLayout) {
  std::vector<size_t> image_sizes;
  std::vector<size_t> image_sizes_extra;
  // Compile multi-image with ImageLayoutA being the last image.
  {
    CompilationHelper helper;
    Compile(ImageHeader::kStorageModeUncompressed,
            /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
            helper,
            "ImageLayoutA",
            {"LMyClass;"});
    image_sizes = helper.GetImageObjectSectionSizes();
  }
  TearDown();
  runtime_.reset();
  SetUp();
  // Compile multi-image with ImageLayoutB being the last image.
  {
    CompilationHelper helper;
    Compile(ImageHeader::kStorageModeUncompressed,
            /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
            helper,
            "ImageLayoutB",
            {"LMyClass;"});
    image_sizes_extra = helper.GetImageObjectSectionSizes();
  }
  // Make sure that the new stuff in the clinit in ImageLayoutB is in the last image and not in the
  // first two images.
  ASSERT_EQ(image_sizes.size(), image_sizes.size());
  // Sizes of the object sections should be the same for all but the last image.
  for (size_t i = 0; i < image_sizes.size() - 1; ++i) {
    EXPECT_EQ(image_sizes[i], image_sizes_extra[i]);
  }
  // Last image should be larger since it has a hash map and a string.
  EXPECT_LT(image_sizes.back(), image_sizes_extra.back());
}

TEST_F(ImageTest, ImageHeaderIsValid) {
  uint32_t image_begin = ART_BASE_ADDRESS;
  uint32_t image_size_ = kElfSegmentAlignment;
  uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
  uint32_t oat_checksum = 0;
  uint32_t oat_file_begin = ART_BASE_ADDRESS + (kElfSegmentAlignment);
  uint32_t oat_data_begin = ART_BASE_ADDRESS + (2 * kElfSegmentAlignment);
  uint32_t oat_data_end = ART_BASE_ADDRESS + (2 * kElfSegmentAlignment + 1 * KB);
  uint32_t oat_file_end = ART_BASE_ADDRESS + (2 * kElfSegmentAlignment + 2 * KB);
  ImageSection sections[ImageHeader::kSectionCount];
  uint32_t image_reservation_size = RoundUp(oat_file_end - image_begin, kElfSegmentAlignment);
  ImageHeader image_header(image_reservation_size,
                           /*component_count=*/ 1u,
                           image_begin,
                           image_size_,
                           sections,
                           image_roots,
                           oat_checksum,
                           oat_file_begin,
                           oat_data_begin,
                           oat_data_end,
                           oat_file_end,
                           /*boot_image_begin=*/ 0u,
                           /*boot_image_size=*/ 0u,
                           /*boot_image_component_count=*/ 0u,
                           /*boot_image_checksum=*/ 0u,
                           kRuntimePointerSize);
  ASSERT_TRUE(image_header.IsValid());

  // Please note that for the following condition to be true, the above values should be chosen in
  // a way that image_reservation_size != RoundUp(image_size_, kElfSegmentAlignment).
  ASSERT_TRUE(!image_header.IsAppImage());

  char* magic = const_cast<char*>(image_header.GetMagic());
  strcpy(magic, "");  // bad magic
  ASSERT_FALSE(image_header.IsValid());
  strcpy(magic, "art\n000");  // bad version
  ASSERT_FALSE(image_header.IsValid());
}

// Test that pointer to quick code is the same in
// a default method of an interface and in a copied method
// of a class which implements the interface. This should be true
// only if the copied method and the origin method are located in the
// same oat file.
TEST_F(ImageTest, TestDefaultMethods) {
  // Use this test to compile managed code to catch crashes when compiling the boot class path.
  // This test already needs to compile some managed methods and by compiling with "speed" we
  // avoid the need to create a specialized profile for the "speed-profile" compilation.
  // (Using "speed" shall compile most methods. We could compile more with "everything".)
  SetCompilerFilter(CompilerFilter::kSpeed);
  CompilationHelper helper;
  Compile(ImageHeader::kStorageModeUncompressed,
          /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
          helper,
          "DefaultMethods",
          {"LIface;", "LImpl;", "LIterableBase;"});

  PointerSize pointer_size = class_linker_->GetImagePointerSize();
  Thread* self = Thread::Current();
  ScopedObjectAccess soa(self);

  // Test the pointer to quick code is the same in origin method
  // and in the copied method from the same oat file.
  ObjPtr<mirror::Class> iface_klass =
      class_linker_->LookupClass(self, "LIface;", /*class_loader=*/ nullptr);
  ASSERT_NE(nullptr, iface_klass);
  ArtMethod* origin = iface_klass->FindInterfaceMethod("defaultMethod", "()V", pointer_size);
  ASSERT_NE(nullptr, origin);
  ASSERT_OBJ_PTR_EQ(origin->GetDeclaringClass(), iface_klass);
  const void* code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
  // The origin method should have a pointer to quick code
  ASSERT_NE(nullptr, code);
  ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
  ObjPtr<mirror::Class> impl_klass =
      class_linker_->LookupClass(self, "LImpl;", /*class_loader=*/ nullptr);
  ASSERT_NE(nullptr, impl_klass);
  ArtMethod* copied = FindCopiedMethod(origin, impl_klass);
  ASSERT_NE(nullptr, copied);
  // the copied method should have pointer to the same quick code as the origin method
  ASSERT_EQ(code, copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size));

  // Test the origin method has pointer to quick code
  // but the copied method has pointer to interpreter
  // because these methods are in different oat files.
  ObjPtr<mirror::Class> iterable_klass =
      class_linker_->LookupClass(self, "Ljava/lang/Iterable;", /*class_loader=*/ nullptr);
  ASSERT_NE(nullptr, iterable_klass);
  origin = iterable_klass->FindClassMethod(
      "forEach", "(Ljava/util/function/Consumer;)V", pointer_size);
  ASSERT_NE(nullptr, origin);
  ASSERT_FALSE(origin->IsDirect());
  ASSERT_OBJ_PTR_EQ(origin->GetDeclaringClass(), iterable_klass);
  code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
  // the origin method should have a pointer to quick code
  ASSERT_NE(nullptr, code);
  ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
  ObjPtr<mirror::Class> iterablebase_klass =
      class_linker_->LookupClass(self, "LIterableBase;", /*class_loader=*/ nullptr);
  ASSERT_NE(nullptr, iterablebase_klass);
  copied = FindCopiedMethod(origin, iterablebase_klass);
  ASSERT_NE(nullptr, copied);
  code = copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
  // the copied method should have a pointer to interpreter
  ASSERT_TRUE(class_linker_->IsQuickToInterpreterBridge(code));
}

// Regression test for dex2oat crash for soft verification failure during
// class initialization check from the transactional interpreter while
// running the class initializer for another class.
TEST_F(ImageTest, TestSoftVerificationFailureDuringClassInitialization) {
  CompilationHelper helper;
  Compile(ImageHeader::kStorageModeUncompressed,
          /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
          helper,
          "VerifySoftFailDuringClinit",
          /*image_classes=*/ {"LClassToInitialize;"},
          /*image_classes_failing_aot_clinit=*/ {"LClassToInitialize;"});
}

TEST_F(ImageTest, TestImageClassWithArrayClassWithUnresolvedComponent) {
  CompilationHelper helper;
  Compile(ImageHeader::kStorageModeUncompressed,
          /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
          helper,
          "ArrayClassWithUnresolvedComponent",
          /*image_classes=*/ {"LClassWithStatic;",
                              "LClassWithStaticConst;",
                              "[LClassWithMissingInterface;",
                              "[[LClassWithMissingInterface;",
                              "[LClassWithMissingSuper",
                              "[[LClassWithMissingSuper"},
          /*image_classes_failing_aot_clinit=*/ {
                              "LClassWithStatic;",
                              "LClassWithStaticConst;"},
          /*image_classes_failing_resolution=*/ {
                              "[LClassWithMissingInterface;",
                              "[[LClassWithMissingInterface;",
                              "[LClassWithMissingSuper",
                              "[[LClassWithMissingSuper"});
}

TEST_F(ImageTest, TestSuperWithAccessChecks) {
  CompilationHelper helper;
  Compile(ImageHeader::kStorageModeUncompressed,
          /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
          helper,
          "SuperWithAccessChecks",
          /*image_classes=*/ {"LSubClass;", "LImplementsClass;"},
          /*image_classes_failing_aot_clinit=*/ {"LSubClass;", "LImplementsClass;"});
}

// Regression test for b/297453985, where we used to generate a bogus image
// checksum.
TEST_F(ImageTest, ImageChecksum) {
  uint32_t image_begin = ART_BASE_ADDRESS;
  uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
  ImageSection sections[ImageHeader::kSectionCount];
  // We require bitmap section to be at least kElfSegmentAlignment.
  sections[ImageHeader::kSectionImageBitmap] = ImageSection(0, kElfSegmentAlignment);
  ImageHeader image_header(/*image_reservation_size=*/ kElfSegmentAlignment,
                           /*component_count=*/ 1u,
                           image_begin,
                           /*image_size=*/ sizeof(ImageHeader),
                           sections,
                           image_roots,
                           /*oat_checksum=*/ 0u,
                           /*oat_file_begin=*/ 0u,
                           /*oat_data_begin=*/ 0u,
                           /*oat_data_end=*/ 0u,
                           /*oat_file_end=*/ 0u,
                           /*boot_image_begin=*/ 0u,
                           /*boot_image_size=*/ 0u,
                           /*boot_image_component_count=*/ 0u,
                           /*boot_image_checksum=*/ 0u,
                           kRuntimePointerSize);
    ASSERT_TRUE(image_header.IsValid());

    std::string error_msg;
    ImageFileGuard image_file;
    ScratchFile location;
    image_file.reset(OS::CreateEmptyFile(location.GetFilename().c_str()));
    const uint8_t* data = reinterpret_cast<const uint8_t*>(&image_header);
    std::unique_ptr<uint8_t> bitmap(new uint8_t[kElfSegmentAlignment]);
    memset(bitmap.get(), 0, kElfSegmentAlignment);
    ASSERT_EQ(image_header.GetImageChecksum(), 0u);
    ASSERT_TRUE(image_header.WriteData(
        image_file,
        data,
        bitmap.get(),
        ImageHeader::kStorageModeUncompressed,
        /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
        /*update_checksum=*/ true,
        &error_msg)) << error_msg;

    uint32_t first_checksum = image_header.GetImageChecksum();
    // Reset the image checksum, `WriteData` updated it.
    image_header.SetImageChecksum(0u);

    // Change the header to ensure the checksum will be different.
    image_header.SetOatChecksum(0xFFFF);

    ASSERT_TRUE(image_header.WriteData(
        image_file,
        data,
        bitmap.get(),
        ImageHeader::kStorageModeUncompressed,
        /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
        /*update_checksum=*/ true,
        &error_msg)) << error_msg;

    ASSERT_NE(first_checksum, image_header.GetImageChecksum());
}

}  // namespace linker
}  // namespace art
