/*
 * Copyright (C) 2019 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 <sys/types.h>

#include <memory>
#include <string>
#include <string_view>

#include <android-base/file.h>
#include <dex/dex_file.h>
#include <gtest/gtest.h>

#include "art_api/dex_file_support.h"

namespace art_api {
namespace dex {

static constexpr uint32_t kDexData[] = {
    0x0a786564, 0x00383330, 0xc98b3ab8, 0xf3749d94, 0xaecca4d8, 0xffc7b09a, 0xdca9ca7f, 0x5be5deab,
    0x00000220, 0x00000070, 0x12345678, 0x00000000, 0x00000000, 0x0000018c, 0x00000008, 0x00000070,
    0x00000004, 0x00000090, 0x00000002, 0x000000a0, 0x00000000, 0x00000000, 0x00000003, 0x000000b8,
    0x00000001, 0x000000d0, 0x00000130, 0x000000f0, 0x00000122, 0x0000012a, 0x00000132, 0x00000146,
    0x00000151, 0x00000154, 0x00000158, 0x0000016d, 0x00000001, 0x00000002, 0x00000004, 0x00000006,
    0x00000004, 0x00000002, 0x00000000, 0x00000005, 0x00000002, 0x0000011c, 0x00000000, 0x00000000,
    0x00010000, 0x00000007, 0x00000001, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000000,
    0x00000003, 0x00000000, 0x0000017e, 0x00000000, 0x00010001, 0x00000001, 0x00000173, 0x00000004,
    0x00021070, 0x000e0000, 0x00010001, 0x00000000, 0x00000178, 0x00000001, 0x0000000e, 0x00000001,
    0x3c060003, 0x74696e69, 0x4c06003e, 0x6e69614d, 0x4c12003b, 0x6176616a, 0x6e616c2f, 0x624f2f67,
    0x7463656a, 0x4d09003b, 0x2e6e6961, 0x6176616a, 0x00560100, 0x004c5602, 0x6a4c5b13, 0x2f617661,
    0x676e616c, 0x7274532f, 0x3b676e69, 0x616d0400, 0x01006e69, 0x000e0700, 0x07000103, 0x0000000e,
    0x81000002, 0x01f00480, 0x02880901, 0x0000000c, 0x00000000, 0x00000001, 0x00000000, 0x00000001,
    0x00000008, 0x00000070, 0x00000002, 0x00000004, 0x00000090, 0x00000003, 0x00000002, 0x000000a0,
    0x00000005, 0x00000003, 0x000000b8, 0x00000006, 0x00000001, 0x000000d0, 0x00002001, 0x00000002,
    0x000000f0, 0x00001001, 0x00000001, 0x0000011c, 0x00002002, 0x00000008, 0x00000122, 0x00002003,
    0x00000002, 0x00000173, 0x00002000, 0x00000001, 0x0000017e, 0x00001000, 0x00000001, 0x0000018c,
};

TEST(DexStringTest, alloc_string) {
  auto s = DexString("123");
  EXPECT_EQ(std::string_view(s), "123");
}

TEST(DexStringTest, alloc_empty_string) {
  auto s = DexString("");
  EXPECT_TRUE(std::string_view(s).empty());
}

TEST(DexStringTest, move_construct) {
  auto s1 = DexString("foo");
  auto s2 = DexString(std::move(s1));
  EXPECT_TRUE(std::string_view(s1).empty()); // NOLINT bugprone-use-after-move
  EXPECT_EQ(std::string_view(s2), "foo");
}

TEST(DexStringTest, move_assign) {
  auto s1 = DexString("foo");
  DexString s2;
  EXPECT_TRUE(std::string_view(s2).empty());
  s2 = std::move(s1);
  EXPECT_TRUE(std::string_view(s1).empty()); // NOLINT bugprone-use-after-move
  EXPECT_EQ(std::string_view(s2), "foo");
}

TEST(DexStringTest, reassign) {
  auto s = DexString("foo");
  s = DexString("bar");
  EXPECT_EQ(std::string_view(s), "bar");
}

TEST(DexStringTest, data_access) {
  auto s = DexString("foo");
  EXPECT_STREQ(s.data(), "foo");
  EXPECT_STREQ(s.c_str(), "foo");
}

TEST(DexStringTest, size_access) {
  auto s = DexString("foo");
  EXPECT_EQ(s.size(), size_t{3});
  EXPECT_EQ(s.length(), size_t{3});
}

TEST(DexStringTest, equality) {
  auto s = DexString("foo");
  EXPECT_EQ(s, DexString("foo"));
  EXPECT_FALSE(s == DexString("bar"));
}

TEST(DexStringTest, equality_with_nul) {
  auto s = DexString(std::string("foo\0bar", 7));
  EXPECT_EQ(s.size(), size_t{7});
  EXPECT_EQ(s, DexString(std::string("foo\0bar", 7)));
  EXPECT_FALSE(s == DexString(std::string("foo\0baz", 7)));
}

TEST(DexFileTest, from_memory_header_too_small) {
  size_t size = sizeof(art::DexFile::Header) - 1;
  std::string error_msg;
  EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
  EXPECT_EQ(size, sizeof(art::DexFile::Header));
  EXPECT_TRUE(error_msg.empty());
}

TEST(DexFileTest, from_memory_file_too_small) {
  size_t size = sizeof(art::DexFile::Header);
  std::string error_msg;
  EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
  EXPECT_EQ(size, sizeof(kDexData));
  EXPECT_TRUE(error_msg.empty());
}

static std::unique_ptr<DexFile> GetTestDexData() {
  size_t size = sizeof(kDexData);
  std::string error_msg;
  std::unique_ptr<DexFile> dex_file = DexFile::OpenFromMemory(kDexData, &size, "", &error_msg);
  EXPECT_TRUE(error_msg.empty());
  return dex_file;
}

TEST(DexFileTest, from_memory) {
  EXPECT_NE(GetTestDexData(), nullptr);
}

TEST(DexFileTest, from_fd_header_too_small) {
  TemporaryFile tf;
  ASSERT_NE(tf.fd, -1);
  ASSERT_EQ(sizeof(art::DexFile::Header) - 1,
            static_cast<size_t>(
                TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header) - 1))));

  std::string error_msg;
  EXPECT_EQ(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
  EXPECT_FALSE(error_msg.empty());
}

TEST(DexFileTest, from_fd_file_too_small) {
  TemporaryFile tf;
  ASSERT_NE(tf.fd, -1);
  ASSERT_EQ(sizeof(art::DexFile::Header),
            static_cast<size_t>(
                TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)))));

  std::string error_msg;
  EXPECT_EQ(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
  EXPECT_FALSE(error_msg.empty());
}

TEST(DexFileTest, from_fd) {
  TemporaryFile tf;
  ASSERT_NE(tf.fd, -1);
  ASSERT_EQ(sizeof(kDexData),
            static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));

  std::string error_msg;
  EXPECT_NE(DexFile::OpenFromFd(tf.fd, 0, tf.path, &error_msg), nullptr);
  EXPECT_TRUE(error_msg.empty());
}

TEST(DexFileTest, from_fd_non_zero_offset) {
  TemporaryFile tf;
  ASSERT_NE(tf.fd, -1);
  ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
  ASSERT_EQ(sizeof(kDexData),
            static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));

  std::string error_msg;
  EXPECT_NE(DexFile::OpenFromFd(tf.fd, 0x100, tf.path, &error_msg), nullptr);
  EXPECT_TRUE(error_msg.empty());
}

TEST(DexFileTest, get_method_info_for_offset_without_signature) {
  std::unique_ptr<DexFile> dex_file = GetTestDexData();
  ASSERT_NE(dex_file, nullptr);

  MethodInfo info = dex_file->GetMethodInfoForOffset(0x102, false);
  EXPECT_EQ(info.offset, int32_t{0x100});
  EXPECT_EQ(info.len, int32_t{8});
  EXPECT_STREQ(info.name.data(), "Main.<init>");

  info = dex_file->GetMethodInfoForOffset(0x118, false);
  EXPECT_EQ(info.offset, int32_t{0x118});
  EXPECT_EQ(info.len, int32_t{2});
  EXPECT_STREQ(info.name.data(), "Main.main");

  // Retrieve a cached result.
  info = dex_file->GetMethodInfoForOffset(0x104, false);
  EXPECT_EQ(info.offset, int32_t{0x100});
  EXPECT_EQ(info.len, int32_t{8});
  EXPECT_STREQ(info.name.data(), "Main.<init>");
}

TEST(DexFileTest, get_method_info_for_offset_with_signature) {
  std::unique_ptr<DexFile> dex_file = GetTestDexData();
  ASSERT_NE(dex_file, nullptr);

  MethodInfo info = dex_file->GetMethodInfoForOffset(0x102, true);
  EXPECT_EQ(info.offset, int32_t{0x100});
  EXPECT_EQ(info.len, int32_t{8});
  EXPECT_STREQ(info.name.data(), "void Main.<init>()");

  info = dex_file->GetMethodInfoForOffset(0x118, true);
  EXPECT_EQ(info.offset, int32_t{0x118});
  EXPECT_EQ(info.len, int32_t{2});
  EXPECT_STREQ(info.name.data(), "void Main.main(java.lang.String[])");

  // Retrieve a cached result.
  info = dex_file->GetMethodInfoForOffset(0x104, true);
  EXPECT_EQ(info.offset, int32_t{0x100});
  EXPECT_EQ(info.len, int32_t{8});
  EXPECT_STREQ(info.name.data(), "void Main.<init>()");

  // with_signature doesn't affect the cache.
  info = dex_file->GetMethodInfoForOffset(0x104, false);
  EXPECT_EQ(info.offset, int32_t{0x100});
  EXPECT_EQ(info.len, int32_t{8});
  EXPECT_STREQ(info.name.data(), "Main.<init>");
}

TEST(DexFileTest, get_method_info_for_offset_boundaries) {
  std::unique_ptr<DexFile> dex_file = GetTestDexData();
  ASSERT_NE(dex_file, nullptr);

  MethodInfo info = dex_file->GetMethodInfoForOffset(0x100000, false);
  EXPECT_EQ(info.offset, int32_t{0});

  info = dex_file->GetMethodInfoForOffset(0x99, false);
  EXPECT_EQ(info.offset, int32_t{0});
  info = dex_file->GetMethodInfoForOffset(0x100, false);
  EXPECT_EQ(info.offset, int32_t{0x100});
  info = dex_file->GetMethodInfoForOffset(0x107, false);
  EXPECT_EQ(info.offset, int32_t{0x100});
  info = dex_file->GetMethodInfoForOffset(0x108, false);
  EXPECT_EQ(info.offset, int32_t{0});

  // Make sure that once the whole dex file has been cached, no problems occur.
  info = dex_file->GetMethodInfoForOffset(0x98, false);
  EXPECT_EQ(info.offset, int32_t{0});

  // Choose a value that is in the cached map, but not in a valid method.
  info = dex_file->GetMethodInfoForOffset(0x110, false);
  EXPECT_EQ(info.offset, int32_t{0});
}

TEST(DexFileTest, get_all_method_infos_without_signature) {
  std::unique_ptr<DexFile> dex_file = GetTestDexData();
  ASSERT_NE(dex_file, nullptr);

  std::vector<MethodInfo> infos;
  infos.emplace_back(MethodInfo{0x100, 8, DexString("Main.<init>")});
  infos.emplace_back(MethodInfo{0x118, 2, DexString("Main.main")});
  ASSERT_EQ(dex_file->GetAllMethodInfos(false), infos);
}

TEST(DexFileTest, get_all_method_infos_with_signature) {
  std::unique_ptr<DexFile> dex_file = GetTestDexData();
  ASSERT_NE(dex_file, nullptr);

  std::vector<MethodInfo> infos;
  infos.emplace_back(MethodInfo{0x100, 8, DexString("void Main.<init>()")});
  infos.emplace_back(MethodInfo{0x118, 2, DexString("void Main.main(java.lang.String[])")});
  ASSERT_EQ(dex_file->GetAllMethodInfos(true), infos);
}

TEST(DexFileTest, move_construct) {
  std::unique_ptr<DexFile> dex_file = GetTestDexData();
  ASSERT_NE(dex_file, nullptr);

  auto df1 = DexFile(std::move(*dex_file));
  auto df2 = DexFile(std::move(df1));

  MethodInfo info = df2.GetMethodInfoForOffset(0x100, false);
  EXPECT_EQ(info.offset, int32_t{0x100});
}

TEST(DexFileTest, pointer_construct) {
  std::unique_ptr<DexFile> dex_file = GetTestDexData();
  ASSERT_NE(dex_file, nullptr);

  auto new_dex = DexFile(dex_file);
  ASSERT_TRUE(dex_file.get() == nullptr);

  MethodInfo info = new_dex.GetMethodInfoForOffset(0x100, false);
  EXPECT_EQ(info.offset, int32_t{0x100});
}

}  // namespace dex
}  // namespace art_api
