1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2021 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <memory>
20*795d594fSAndroid Build Coastguard Worker #include <string>
21*795d594fSAndroid Build Coastguard Worker #include <string_view>
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Worker #include <android-base/file.h>
24*795d594fSAndroid Build Coastguard Worker #include <dex/dex_file.h>
25*795d594fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker #include "art_api/dex_file_external.h"
28*795d594fSAndroid Build Coastguard Worker #include "dex_file_test_data.h"
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker namespace art_api {
31*795d594fSAndroid Build Coastguard Worker namespace dex {
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker class ADexFileTest : public ::testing::Test {
34*795d594fSAndroid Build Coastguard Worker protected:
TearDown()35*795d594fSAndroid Build Coastguard Worker void TearDown() override {
36*795d594fSAndroid Build Coastguard Worker ADexFile_destroy(dex_);
37*795d594fSAndroid Build Coastguard Worker }
38*795d594fSAndroid Build Coastguard Worker
39*795d594fSAndroid Build Coastguard Worker ADexFile* dex_ = nullptr;
40*795d594fSAndroid Build Coastguard Worker };
41*795d594fSAndroid Build Coastguard Worker
TEST_F(ADexFileTest,create)42*795d594fSAndroid Build Coastguard Worker TEST_F(ADexFileTest, create) {
43*795d594fSAndroid Build Coastguard Worker size_t size = sizeof(kDexData);
44*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_create(kDexData, size, &size, "", &dex_), ADEXFILE_ERROR_OK);
45*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(size, sizeof(kDexData));
46*795d594fSAndroid Build Coastguard Worker EXPECT_NE(dex_, nullptr);
47*795d594fSAndroid Build Coastguard Worker }
48*795d594fSAndroid Build Coastguard Worker
TEST_F(ADexFileTest,create_null_new_size)49*795d594fSAndroid Build Coastguard Worker TEST_F(ADexFileTest, create_null_new_size) {
50*795d594fSAndroid Build Coastguard Worker const size_t size = sizeof(kDexData);
51*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_create(kDexData, size, nullptr, "", &dex_), ADEXFILE_ERROR_OK);
52*795d594fSAndroid Build Coastguard Worker EXPECT_NE(dex_, nullptr);
53*795d594fSAndroid Build Coastguard Worker }
54*795d594fSAndroid Build Coastguard Worker
TEST_F(ADexFileTest,create_header_too_small)55*795d594fSAndroid Build Coastguard Worker TEST_F(ADexFileTest, create_header_too_small) {
56*795d594fSAndroid Build Coastguard Worker size_t size = sizeof(art::DexFile::Header) - 1;
57*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_create(kDexData, size, &size, "", &dex_), ADEXFILE_ERROR_NOT_ENOUGH_DATA);
58*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(size, sizeof(art::DexFile::Header));
59*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(dex_, nullptr);
60*795d594fSAndroid Build Coastguard Worker }
61*795d594fSAndroid Build Coastguard Worker
TEST_F(ADexFileTest,create_file_too_small)62*795d594fSAndroid Build Coastguard Worker TEST_F(ADexFileTest, create_file_too_small) {
63*795d594fSAndroid Build Coastguard Worker size_t size = sizeof(art::DexFile::Header);
64*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_create(kDexData, size, &size, "", &dex_), ADEXFILE_ERROR_NOT_ENOUGH_DATA);
65*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(size, sizeof(kDexData));
66*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(dex_, nullptr);
67*795d594fSAndroid Build Coastguard Worker }
68*795d594fSAndroid Build Coastguard Worker
GetTestDexData()69*795d594fSAndroid Build Coastguard Worker static ADexFile* GetTestDexData() {
70*795d594fSAndroid Build Coastguard Worker size_t size = sizeof(kDexData);
71*795d594fSAndroid Build Coastguard Worker ADexFile* dex;
72*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_create(kDexData, size, &size, "", &dex), ADEXFILE_ERROR_OK);
73*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(size, sizeof(kDexData));
74*795d594fSAndroid Build Coastguard Worker EXPECT_NE(dex, nullptr);
75*795d594fSAndroid Build Coastguard Worker return dex;
76*795d594fSAndroid Build Coastguard Worker }
77*795d594fSAndroid Build Coastguard Worker
TEST_F(ADexFileTest,findMethodAtOffset)78*795d594fSAndroid Build Coastguard Worker TEST_F(ADexFileTest, findMethodAtOffset) {
79*795d594fSAndroid Build Coastguard Worker dex_ = GetTestDexData();
80*795d594fSAndroid Build Coastguard Worker ASSERT_NE(dex_, nullptr);
81*795d594fSAndroid Build Coastguard Worker
82*795d594fSAndroid Build Coastguard Worker bool found_init = false;
83*795d594fSAndroid Build Coastguard Worker auto check_init = [](void* ctx, const ADexFile_Method* method) {
84*795d594fSAndroid Build Coastguard Worker size_t size;
85*795d594fSAndroid Build Coastguard Worker size_t offset = ADexFile_Method_getCodeOffset(method, &size);
86*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(offset, 0x100u);
87*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(size, 8u);
88*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ADexFile_Method_getName(method, &size), "<init>");
89*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ADexFile_Method_getQualifiedName(method, false, &size), "Main.<init>");
90*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ADexFile_Method_getQualifiedName(method, true, &size), "void Main.<init>()");
91*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ADexFile_Method_getClassDescriptor(method, &size), "LMain;");
92*795d594fSAndroid Build Coastguard Worker *reinterpret_cast<bool*>(ctx) = true;
93*795d594fSAndroid Build Coastguard Worker };
94*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x102, check_init, &found_init), 1u);
95*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(found_init);
96*795d594fSAndroid Build Coastguard Worker
97*795d594fSAndroid Build Coastguard Worker bool found_main = false;
98*795d594fSAndroid Build Coastguard Worker auto check_main = [](void* ctx, const ADexFile_Method* method) {
99*795d594fSAndroid Build Coastguard Worker size_t size;
100*795d594fSAndroid Build Coastguard Worker size_t offset = ADexFile_Method_getCodeOffset(method, &size);
101*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(offset, 0x118u);
102*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(size, 2u);
103*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ADexFile_Method_getName(method, &size), "main");
104*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ADexFile_Method_getQualifiedName(method, false, &size), "Main.main");
105*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ADexFile_Method_getQualifiedName(method, true, &size), "void Main.main(java.lang.String[])");
106*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ADexFile_Method_getClassDescriptor(method, &size), "LMain;");
107*795d594fSAndroid Build Coastguard Worker *reinterpret_cast<bool*>(ctx) = true;
108*795d594fSAndroid Build Coastguard Worker };
109*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x118, check_main, &found_main), 1u);
110*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(found_main);
111*795d594fSAndroid Build Coastguard Worker }
112*795d594fSAndroid Build Coastguard Worker
TEST_F(ADexFileTest,findMethodAtOffset_for_offset_boundaries)113*795d594fSAndroid Build Coastguard Worker TEST_F(ADexFileTest, findMethodAtOffset_for_offset_boundaries) {
114*795d594fSAndroid Build Coastguard Worker dex_ = GetTestDexData();
115*795d594fSAndroid Build Coastguard Worker ASSERT_NE(dex_, nullptr);
116*795d594fSAndroid Build Coastguard Worker
117*795d594fSAndroid Build Coastguard Worker auto no_cb = [](void*, const ADexFile_Method*) {};
118*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x99, no_cb, nullptr), 0);
119*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x100, no_cb, nullptr), 1);
120*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x107, no_cb, nullptr), 1);
121*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x108, no_cb, nullptr), 0);
122*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_findMethodAtOffset(dex_, 0x100000, no_cb, nullptr), 0);
123*795d594fSAndroid Build Coastguard Worker }
124*795d594fSAndroid Build Coastguard Worker
TEST_F(ADexFileTest,forEachMethod)125*795d594fSAndroid Build Coastguard Worker TEST_F(ADexFileTest, forEachMethod) {
126*795d594fSAndroid Build Coastguard Worker dex_ = GetTestDexData();
127*795d594fSAndroid Build Coastguard Worker ASSERT_NE(dex_, nullptr);
128*795d594fSAndroid Build Coastguard Worker
129*795d594fSAndroid Build Coastguard Worker std::vector<std::string> names;
130*795d594fSAndroid Build Coastguard Worker auto add = [](void* ctx, const ADexFile_Method* method) {
131*795d594fSAndroid Build Coastguard Worker reinterpret_cast<decltype(names)*>(ctx)->
132*795d594fSAndroid Build Coastguard Worker push_back(ADexFile_Method_getQualifiedName(method, false, nullptr));
133*795d594fSAndroid Build Coastguard Worker };
134*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(ADexFile_forEachMethod(dex_, add, &names), 2u);
135*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(names, std::vector<std::string>({"Main.<init>", "Main.main"}));
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker
TEST_F(ADexFileTest,Error_toString)138*795d594fSAndroid Build Coastguard Worker TEST_F(ADexFileTest, Error_toString) {
139*795d594fSAndroid Build Coastguard Worker constexpr size_t kNumErrors = 4;
140*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < kNumErrors; i++) {
141*795d594fSAndroid Build Coastguard Worker const char* err = ADexFile_Error_toString(static_cast<ADexFile_Error>(i));
142*795d594fSAndroid Build Coastguard Worker ASSERT_NE(err, nullptr);
143*795d594fSAndroid Build Coastguard Worker ASSERT_FALSE(std::string_view(err).empty());
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker const char* err = ADexFile_Error_toString(static_cast<ADexFile_Error>(kNumErrors));
146*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(err, nullptr);
147*795d594fSAndroid Build Coastguard Worker }
148*795d594fSAndroid Build Coastguard Worker
149*795d594fSAndroid Build Coastguard Worker } // namespace dex
150*795d594fSAndroid Build Coastguard Worker } // namespace art_api
151