summaryrefslogtreecommitdiff
path: root/libdexfile/external/dex_file_supp_test.cc
diff options
context:
space:
mode:
authorDavid Srbecky <dsrbecky@google.com>2021-03-24 16:11:49 +0000
committerDavid Srbecky <dsrbecky@google.com>2021-04-21 18:57:13 +0000
commit30d4d2f8dba0d7cd29cb0eeee53883d73542b7cc (patch)
treef670c2fed029ac132b1be91544bd470310f66efc /libdexfile/external/dex_file_supp_test.cc
parent18584d13da8af452c79e3909617f969fc1f3f455 (diff)
Rewrite libdexfile C API to follow NDK guidelines better.
Bug: 123517037 Bug: 145347927 Test: test-art-host-gtest-art_libdexfile_support_tests64 Test: test-art-host-gtest-art_libdexfile_external_tests64 Change-Id: I9673872585456937d2f54abb63e3dbd8aad4e9ad
Diffstat (limited to 'libdexfile/external/dex_file_supp_test.cc')
-rw-r--r--libdexfile/external/dex_file_supp_test.cc246
1 files changed, 66 insertions, 180 deletions
diff --git a/libdexfile/external/dex_file_supp_test.cc b/libdexfile/external/dex_file_supp_test.cc
index ff263fc539..3285edf435 100644
--- a/libdexfile/external/dex_file_supp_test.cc
+++ b/libdexfile/external/dex_file_supp_test.cc
@@ -25,218 +25,104 @@
#include <gtest/gtest.h>
#include "art_api/dex_file_support.h"
+#include "dex_file_test_data.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(DexFileTest, from_memory_header_too_small) {
+TEST(DexFileTest, create) {
+ size_t size = sizeof(kDexData);
+ std::unique_ptr<DexFile> dex_file;
+ EXPECT_TRUE(DexFile::Create(kDexData, size, &size, "", &dex_file).Ok());
+ EXPECT_EQ(size, sizeof(kDexData));
+ EXPECT_NE(dex_file, nullptr);
+}
+
+TEST(DexFileTest, create_header_too_small) {
size_t size = sizeof(art::DexFile::Header) - 1;
- std::string error_msg;
- EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
+ std::unique_ptr<DexFile> dex_file;
+ DexFile::Error error = DexFile::Create(kDexData, size, &size, "", &dex_file);
+ EXPECT_FALSE(error.Ok());
+ EXPECT_EQ(error.Code(), ADEXFILE_ERROR_NOT_ENOUGH_DATA);
+ EXPECT_STREQ(error.ToString(), "Not enough data. Incomplete dex file.");
EXPECT_EQ(size, sizeof(art::DexFile::Header));
- EXPECT_FALSE(error_msg.empty());
+ EXPECT_EQ(dex_file, nullptr);
}
-TEST(DexFileTest, from_memory_file_too_small) {
+TEST(DexFileTest, create_file_too_small) {
size_t size = sizeof(art::DexFile::Header);
- std::string error_msg;
- EXPECT_EQ(DexFile::OpenFromMemory(kDexData, &size, "", &error_msg), nullptr);
+ std::unique_ptr<DexFile> dex_file;
+ DexFile::Error error = DexFile::Create(kDexData, size, &size, "", &dex_file);
+ EXPECT_FALSE(error.Ok());
+ EXPECT_EQ(error.Code(), ADEXFILE_ERROR_NOT_ENOUGH_DATA);
+ EXPECT_STREQ(error.ToString(), "Not enough data. Incomplete dex file.");
EXPECT_EQ(size, sizeof(kDexData));
- EXPECT_FALSE(error_msg.empty());
+ EXPECT_EQ(dex_file, nullptr);
}
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());
+ std::unique_ptr<DexFile> dex_file;
+ EXPECT_TRUE(DexFile::Create(kDexData, size, &size, "", &dex_file).Ok());
+ EXPECT_EQ(size, sizeof(kDexData));
+ EXPECT_NE(dex_file, nullptr);
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) {
+TEST(DexFileTest, findMethodAtOffset) {
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>");
+ bool found_init = false;
+ auto check_init = [&](const DexFile::Method& method) {
+ size_t size;
+ size_t offset = method.GetCodeOffset(&size);
+ EXPECT_EQ(offset, 0x100u);
+ EXPECT_EQ(size, 8u);
+ EXPECT_STREQ(method.GetName(), "<init>");
+ EXPECT_STREQ(method.GetQualifiedName(), "Main.<init>");
+ EXPECT_STREQ(method.GetQualifiedName(true), "void Main.<init>()");
+ EXPECT_STREQ(method.GetClassDescriptor(), "LMain;");
+ found_init = true;
+ };
+ EXPECT_EQ(dex_file->FindMethodAtOffset(0x102, check_init), 1u);
+ EXPECT_TRUE(found_init);
+
+ bool found_main = false;
+ auto check_main = [&](const DexFile::Method& method) {
+ size_t size;
+ size_t offset = method.GetCodeOffset(&size);
+ EXPECT_EQ(offset, 0x118u);
+ EXPECT_EQ(size, 2u);
+ EXPECT_STREQ(method.GetName(), "main");
+ EXPECT_STREQ(method.GetQualifiedName(), "Main.main");
+ EXPECT_STREQ(method.GetQualifiedName(true), "void Main.main(java.lang.String[])");
+ EXPECT_STREQ(method.GetClassDescriptor(), "LMain;");
+ found_main = true;
+ };
+ EXPECT_EQ(dex_file->FindMethodAtOffset(0x118, check_main), 1u);
+ EXPECT_TRUE(found_main);
}
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});
+ EXPECT_EQ(dex_file->FindMethodAtOffset(0x99, [](auto){}), 0);
+ EXPECT_EQ(dex_file->FindMethodAtOffset(0x100, [](auto){}), 1);
+ EXPECT_EQ(dex_file->FindMethodAtOffset(0x107, [](auto){}), 1);
+ EXPECT_EQ(dex_file->FindMethodAtOffset(0x108, [](auto){}), 0);
+ EXPECT_EQ(dex_file->FindMethodAtOffset(0x100000, [](auto){}), 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, std::string("Main.<init>")});
- infos.emplace_back(MethodInfo{0x118, 2, std::string("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, std::string("void Main.<init>()")});
- infos.emplace_back(MethodInfo{0x118, 2, std::string("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});
+ std::vector<std::string> names;
+ auto add = [&](const DexFile::Method& method) { names.push_back(method.GetQualifiedName()); };
+ EXPECT_EQ(dex_file->ForEachMethod(add), 2u);
+ EXPECT_EQ(names, std::vector<std::string>({"Main.<init>", "Main.main"}));
}
} // namespace dex