blob: 4643e78226bbfb12d7982531de84c80058af2ecf [file] [log] [blame]
Calin Juravle87e2cb62017-06-13 21:48:45 -07001/*
2 * Copyright (C) 2017 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 <gtest/gtest.h>
18
19
20#include "class_loader_context.h"
21#include "common_runtime_test.h"
22
23#include "base/dchecked_vector.h"
24#include "base/stl_util.h"
25#include "class_linker.h"
26#include "dex_file.h"
27#include "handle_scope-inl.h"
28#include "mirror/class.h"
29#include "mirror/class_loader.h"
30#include "mirror/object-inl.h"
31#include "oat_file_assistant.h"
32#include "runtime.h"
33#include "scoped_thread_state_change-inl.h"
34#include "thread.h"
35#include "well_known_classes.h"
36
37namespace art {
38
39class ClassLoaderContextTest : public CommonRuntimeTest {
40 public:
41 void VerifyContextSize(ClassLoaderContext* context, size_t expected_size) {
42 ASSERT_TRUE(context != nullptr);
43 ASSERT_EQ(expected_size, context->class_loader_chain_.size());
44 }
45
46 void VerifyClassLoaderPCL(ClassLoaderContext* context,
47 size_t index,
48 std::string classpath) {
49 VerifyClassLoaderInfo(
50 context, index, ClassLoaderContext::kPathClassLoader, classpath);
51 }
52
53 void VerifyClassLoaderDLC(ClassLoaderContext* context,
54 size_t index,
55 std::string classpath) {
56 VerifyClassLoaderInfo(
57 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath);
58 }
59
60 void VerifyOpenDexFiles(
61 ClassLoaderContext* context,
62 size_t index,
63 std::vector<std::vector<std::unique_ptr<const DexFile>>*>& all_dex_files) {
64 ASSERT_TRUE(context != nullptr);
65 ASSERT_TRUE(context->dex_files_open_attempted_);
66 ASSERT_TRUE(context->dex_files_open_result_);
67 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
68 ASSERT_EQ(all_dex_files.size(), info.classpath.size());
69 size_t cur_open_dex_index = 0;
70 for (size_t k = 0; k < all_dex_files.size(); k++) {
71 std::vector<std::unique_ptr<const DexFile>>& dex_files_for_cp_elem = *(all_dex_files[k]);
72 for (size_t i = 0; i < dex_files_for_cp_elem.size(); i++) {
73 ASSERT_LT(cur_open_dex_index, info.opened_dex_files.size());
74
75 std::unique_ptr<const DexFile>& opened_dex_file =
76 info.opened_dex_files[cur_open_dex_index++];
77 std::unique_ptr<const DexFile>& expected_dex_file = dex_files_for_cp_elem[i];
78
79 ASSERT_EQ(expected_dex_file->GetLocation(), opened_dex_file->GetLocation());
80 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
81 ASSERT_EQ(info.classpath[k], opened_dex_file->GetBaseLocation());
82 }
83 }
84 }
85
86 private:
87 void VerifyClassLoaderInfo(ClassLoaderContext* context,
88 size_t index,
89 ClassLoaderContext::ClassLoaderType type,
90 std::string classpath) {
91 ASSERT_TRUE(context != nullptr);
92 ASSERT_GT(context->class_loader_chain_.size(), index);
93 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
94 ASSERT_EQ(type, info.type);
95 std::vector<std::string> expected_classpath;
96 Split(classpath, ':', &expected_classpath);
97 ASSERT_EQ(expected_classpath, info.classpath);
98 }
99};
100
101TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
102 std::unique_ptr<ClassLoaderContext> context =
103 ClassLoaderContext::Create("PCL[a.dex]");
104 VerifyContextSize(context.get(), 1);
105 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
106}
107
108TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
109 std::unique_ptr<ClassLoaderContext> context =
110 ClassLoaderContext::Create("DLC[a.dex]");
111 VerifyContextSize(context.get(), 1);
112 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
113}
114
115TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
116 std::unique_ptr<ClassLoaderContext> context =
117 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
118 VerifyContextSize(context.get(), 3);
119 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
120 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
121 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
122}
123
124TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
125 std::unique_ptr<ClassLoaderContext> context =
126 ClassLoaderContext::Create("DLC[]");
127 VerifyContextSize(context.get(), 1);
128 VerifyClassLoaderDLC(context.get(), 0, "");
129}
130
131TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
132 std::unique_ptr<ClassLoaderContext> context =
133 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
134 VerifyContextSize(context.get(), 0);
135}
136
137TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
138 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
139 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
140 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
141 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
142 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
143 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
144}
145
146TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
147 std::unique_ptr<ClassLoaderContext> context =
148 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
149 VerifyContextSize(context.get(), 1);
150 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
151}
152
153TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
154 std::string multidex_name = GetTestDexFileName("MultiDex");
155 std::vector<std::unique_ptr<const DexFile>> multidex_files = OpenTestDexFiles("MultiDex");
156 std::string myclass_dex_name = GetTestDexFileName("MyClass");
157 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
158 std::string dex_name = GetTestDexFileName("Main");
159 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
160
161
162 std::unique_ptr<ClassLoaderContext> context =
163 ClassLoaderContext::Create(
164 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
165 "DLC[" + dex_name + "]");
166
167 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
168
169 VerifyContextSize(context.get(), 2);
170 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
171 all_dex_files0.push_back(&multidex_files);
172 all_dex_files0.push_back(&myclass_dex_files);
173 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files1;
174 all_dex_files1.push_back(&dex_files);
175
176 VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
177 VerifyOpenDexFiles(context.get(), 1, all_dex_files1);
178}
179
180TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
181 std::string dex_name = GetTestDexFileName("Main");
182 std::unique_ptr<ClassLoaderContext> context =
183 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
184 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
185}
186
187TEST_F(ClassLoaderContextTest, CreateClassLoader) {
188 std::string dex_name = GetTestDexFileName("Main");
189 std::unique_ptr<ClassLoaderContext> context =
190 ClassLoaderContext::Create("PCL[" + dex_name + "]");
191 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
192
193 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
194 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
195
196 std::vector<const DexFile*> compilation_sources_raw =
197 MakeNonOwningPointerVector(compilation_sources);
198 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
199 ASSERT_TRUE(jclass_loader != nullptr);
200
201 ScopedObjectAccess soa(Thread::Current());
202
203 StackHandleScope<2> hs(soa.Self());
204 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
205 soa.Decode<mirror::ClassLoader>(jclass_loader));
206
207 ASSERT_TRUE(class_loader->GetClass() ==
208 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
209 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
210 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
211
212
213 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(jclass_loader);
214 ASSERT_EQ(classpath_dex.size() + compilation_sources.size(), class_loader_dex_files.size());
215
216 // The classpath dex files must come first.
217 for (size_t i = 0; i < classpath_dex.size(); i++) {
218 ASSERT_EQ(classpath_dex[i]->GetLocation(),
219 class_loader_dex_files[i]->GetLocation());
220 ASSERT_EQ(classpath_dex[i]->GetLocationChecksum(),
221 class_loader_dex_files[i]->GetLocationChecksum());
222 }
223
224 // The compilation dex files must come second.
225 for (size_t i = 0, k = classpath_dex.size(); i < compilation_sources.size(); i++, k++) {
226 ASSERT_EQ(compilation_sources[i]->GetLocation(),
227 class_loader_dex_files[k]->GetLocation());
228 ASSERT_EQ(compilation_sources[i]->GetLocationChecksum(),
229 class_loader_dex_files[k]->GetLocationChecksum());
230 }
231}
232
233TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
234 std::unique_ptr<ClassLoaderContext> context =
235 ClassLoaderContext::Create("PCL[a.dex]");
236 dchecked_vector<std::string> classpath_dex;
237 classpath_dex.push_back("a.dex");
238 dchecked_vector<std::string> compilation_sources;
239 compilation_sources.push_back("src.dex");
240
241 // Nothing should be removed.
242 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
243 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
244 // Classes should be removed.
245 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
246 VerifyClassLoaderPCL(context.get(), 0, "");
247}
248
249TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
250 std::string dex1_name = GetTestDexFileName("Main");
251 std::string dex2_name = GetTestDexFileName("MyClass");
252 std::unique_ptr<ClassLoaderContext> context =
253 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
254 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
255
256 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
257 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
258 std::string encoding = context->EncodeContextForOatFile("");
259 std::string expected_encoding =
260 dex1[0]->GetLocation() + "*" + std::to_string(dex1[0]->GetLocationChecksum()) + "*" +
261 dex2[0]->GetLocation() + "*" + std::to_string(dex2[0]->GetLocationChecksum()) + "*";
262 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
263}
264
265} // namespace art