blob: 0b02c5bf18acf3329e60e647d10e03015dcab3cc [file] [log] [blame]
Christopher Ferris0b06a592018-01-19 10:26:36 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdint.h>
18#include <sys/types.h>
19#include <unistd.h>
20
21#include <unordered_map>
22
23#include <android-base/test_utils.h>
24
25#include <unwindstack/MapInfo.h>
26#include <unwindstack/Memory.h>
27
David Sehr892e6752018-02-07 15:19:22 -080028#include <dex/code_item_accessors-inl.h>
Christopher Ferris0b06a592018-01-19 10:26:36 -080029#include <dex/standard_dex_file.h>
30
31#include <gtest/gtest.h>
32
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080033#include "DexFile.h"
Christopher Ferris0b06a592018-01-19 10:26:36 -080034
Christopher Ferris7747b602018-01-31 19:05:19 -080035#include "DexFileData.h"
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080036#include "MemoryFake.h"
Christopher Ferris0b06a592018-01-19 10:26:36 -080037
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080038namespace unwindstack {
Christopher Ferris0b06a592018-01-19 10:26:36 -080039
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080040TEST(DexFileTest, from_file_open_non_exist) {
41 DexFileFromFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080042 ASSERT_FALSE(dex_file.Open(0, "/file/does/not/exist"));
43}
44
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080045TEST(DexFileTest, from_file_open_too_small) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080046 TemporaryFile tf;
47 ASSERT_TRUE(tf.fd != -1);
48
49 ASSERT_EQ(sizeof(art::DexFile::Header) - 2,
50 static_cast<size_t>(
51 TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header)) - 2)));
52
53 // Header too small.
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080054 DexFileFromFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080055 ASSERT_FALSE(dex_file.Open(0, tf.path));
56
57 // Header correct, file too small.
58 ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
59 ASSERT_EQ(sizeof(art::DexFile::Header), static_cast<size_t>(TEMP_FAILURE_RETRY(write(
60 tf.fd, kDexData, sizeof(art::DexFile::Header)))));
61 ASSERT_FALSE(dex_file.Open(0, tf.path));
62}
63
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080064TEST(DexFileTest, from_file_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080065 TemporaryFile tf;
66 ASSERT_TRUE(tf.fd != -1);
67
68 ASSERT_EQ(sizeof(kDexData),
69 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
70
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080071 DexFileFromFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080072 ASSERT_TRUE(dex_file.Open(0, tf.path));
73}
74
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080075TEST(DexFileTest, from_file_open_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080076 TemporaryFile tf;
77 ASSERT_TRUE(tf.fd != -1);
78
79 ASSERT_EQ(0x100, lseek(tf.fd, 0x100, SEEK_SET));
80 ASSERT_EQ(sizeof(kDexData),
81 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
82
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080083 DexFileFromFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080084 ASSERT_TRUE(dex_file.Open(0x100, tf.path));
85}
86
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080087TEST(DexFileTest, from_memory_fail_too_small_for_header) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080088 MemoryFake memory;
89
90 memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080091 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -080092
93 ASSERT_FALSE(dex_file.Open(0x1000, &memory));
94}
95
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080096TEST(DexFileTest, from_memory_fail_too_small_for_data) {
Christopher Ferris0b06a592018-01-19 10:26:36 -080097 MemoryFake memory;
98
99 memory.SetMemory(0x1000, kDexData, sizeof(kDexData) - 2);
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800100 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -0800101
102 ASSERT_FALSE(dex_file.Open(0x1000, &memory));
103}
104
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800105TEST(DexFileTest, from_memory_open) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800106 MemoryFake memory;
107
108 memory.SetMemory(0x1000, kDexData, sizeof(kDexData));
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800109 DexFileFromMemory dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -0800110
111 ASSERT_TRUE(dex_file.Open(0x1000, &memory));
112}
113
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800114TEST(DexFileTest, create_using_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800115 TemporaryFile tf;
116 ASSERT_TRUE(tf.fd != -1);
117
118 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
119 ASSERT_EQ(sizeof(kDexData),
120 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
121
122 MemoryFake memory;
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800123 MapInfo info(0, 0x10000, 0, 0x5, tf.path);
124 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x500, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800125 ASSERT_TRUE(dex_file != nullptr);
126}
127
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800128TEST(DexFileTest, create_using_file_non_zero_start) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800129 TemporaryFile tf;
130 ASSERT_TRUE(tf.fd != -1);
131
132 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
133 ASSERT_EQ(sizeof(kDexData),
134 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
135
136 MemoryFake memory;
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800137 MapInfo info(0x100, 0x10000, 0, 0x5, tf.path);
138 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x600, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800139 ASSERT_TRUE(dex_file != nullptr);
140}
141
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800142TEST(DexFileTest, create_using_file_non_zero_offset) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800143 TemporaryFile tf;
144 ASSERT_TRUE(tf.fd != -1);
145
146 ASSERT_EQ(0x500, lseek(tf.fd, 0x500, SEEK_SET));
147 ASSERT_EQ(sizeof(kDexData),
148 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData)))));
149
150 MemoryFake memory;
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800151 MapInfo info(0x100, 0x10000, 0x200, 0x5, tf.path);
152 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x400, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800153 ASSERT_TRUE(dex_file != nullptr);
154}
155
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800156TEST(DexFileTest, create_using_memory_empty_file) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800157 MemoryFake memory;
158 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800159 MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
160 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800161 ASSERT_TRUE(dex_file != nullptr);
162}
163
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800164TEST(DexFileTest, create_using_memory_file_does_not_exist) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800165 MemoryFake memory;
166 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800167 MapInfo info(0x100, 0x10000, 0x200, 0x5, "/does/not/exist");
168 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800169 ASSERT_TRUE(dex_file != nullptr);
170}
171
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800172TEST(DexFileTest, create_using_memory_file_is_malformed) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800173 TemporaryFile tf;
174 ASSERT_TRUE(tf.fd != -1);
175
176 ASSERT_EQ(sizeof(kDexData) - 10,
177 static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 10))));
178
179 MemoryFake memory;
180 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800181 MapInfo info(0x4000, 0x10000, 0x200, 0x5, "/does/not/exist");
182 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800183 ASSERT_TRUE(dex_file != nullptr);
184
185 // Check it came from memory by clearing memory and verifying it fails.
186 memory.Clear();
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800187 dex_file.reset(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800188 ASSERT_TRUE(dex_file == nullptr);
189}
190
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800191TEST(DexFileTest, get_method_not_opened) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800192 std::string method("something");
193 uint64_t method_offset = 100;
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800194 DexFile dex_file;
Christopher Ferris0b06a592018-01-19 10:26:36 -0800195 dex_file.GetMethodInformation(0x100, &method, &method_offset);
196 EXPECT_EQ("something", method);
197 EXPECT_EQ(100U, method_offset);
198}
199
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800200TEST(DexFileTest, get_method) {
Christopher Ferris0b06a592018-01-19 10:26:36 -0800201 MemoryFake memory;
202 memory.SetMemory(0x4000, kDexData, sizeof(kDexData));
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800203 MapInfo info(0x100, 0x10000, 0x200, 0x5, "");
204 std::unique_ptr<DexFile> dex_file(DexFile::Create(0x4000, &memory, &info));
Christopher Ferris0b06a592018-01-19 10:26:36 -0800205 ASSERT_TRUE(dex_file != nullptr);
206
207 std::string method;
208 uint64_t method_offset;
209 dex_file->GetMethodInformation(0x102, &method, &method_offset);
210 EXPECT_EQ("Main.<init>", method);
211 EXPECT_EQ(2U, method_offset);
212
213 method = "not_in_a_method";
214 method_offset = 0x123;
215 dex_file->GetMethodInformation(0x100000, &method, &method_offset);
216 EXPECT_EQ("not_in_a_method", method);
217 EXPECT_EQ(0x123U, method_offset);
218}
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800219
220} // namespace unwindstack