blob: 659db4be64822f016dc6de9e810d8375c672a441 [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,
Calin Juravle57d0acc2017-07-11 17:41:30 -070048 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070049 VerifyClassLoaderInfo(
50 context, index, ClassLoaderContext::kPathClassLoader, classpath);
51 }
52
53 void VerifyClassLoaderDLC(ClassLoaderContext* context,
54 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070055 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070056 VerifyClassLoaderInfo(
57 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath);
58 }
59
Calin Juravle57d0acc2017-07-11 17:41:30 -070060 void VerifyClassLoaderPCLFromTestDex(ClassLoaderContext* context,
61 size_t index,
62 const std::string& test_name) {
63 VerifyClassLoaderFromTestDex(
64 context, index, ClassLoaderContext::kPathClassLoader, test_name);
65 }
66
67 void VerifyClassLoaderDLCFromTestDex(ClassLoaderContext* context,
68 size_t index,
69 const std::string& test_name) {
70 VerifyClassLoaderFromTestDex(
71 context, index, ClassLoaderContext::kDelegateLastClassLoader, test_name);
72 }
73
Calin Juravle87e2cb62017-06-13 21:48:45 -070074 void VerifyOpenDexFiles(
75 ClassLoaderContext* context,
76 size_t index,
77 std::vector<std::vector<std::unique_ptr<const DexFile>>*>& all_dex_files) {
78 ASSERT_TRUE(context != nullptr);
79 ASSERT_TRUE(context->dex_files_open_attempted_);
80 ASSERT_TRUE(context->dex_files_open_result_);
81 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
82 ASSERT_EQ(all_dex_files.size(), info.classpath.size());
83 size_t cur_open_dex_index = 0;
84 for (size_t k = 0; k < all_dex_files.size(); k++) {
85 std::vector<std::unique_ptr<const DexFile>>& dex_files_for_cp_elem = *(all_dex_files[k]);
86 for (size_t i = 0; i < dex_files_for_cp_elem.size(); i++) {
87 ASSERT_LT(cur_open_dex_index, info.opened_dex_files.size());
88
89 std::unique_ptr<const DexFile>& opened_dex_file =
90 info.opened_dex_files[cur_open_dex_index++];
91 std::unique_ptr<const DexFile>& expected_dex_file = dex_files_for_cp_elem[i];
92
93 ASSERT_EQ(expected_dex_file->GetLocation(), opened_dex_file->GetLocation());
94 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
95 ASSERT_EQ(info.classpath[k], opened_dex_file->GetBaseLocation());
96 }
97 }
98 }
99
Calin Juravle57d0acc2017-07-11 17:41:30 -0700100 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
101 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
102 }
103
Calin Juravle3f918642017-07-11 19:04:20 -0700104 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
105 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
106 if (!context->Parse(context_spec, /*parse_checksums*/ true)) {
107 return nullptr;
108 }
109 return context;
110 }
111
Calin Juravle57d0acc2017-07-11 17:41:30 -0700112 void VerifyContextForClassLoader(ClassLoaderContext* context) {
113 ASSERT_TRUE(context != nullptr);
114 ASSERT_TRUE(context->dex_files_open_attempted_);
115 ASSERT_TRUE(context->dex_files_open_result_);
116 ASSERT_FALSE(context->owns_the_dex_files_);
117 ASSERT_FALSE(context->special_shared_library_);
118 }
119
Calin Juravle87e2cb62017-06-13 21:48:45 -0700120 private:
121 void VerifyClassLoaderInfo(ClassLoaderContext* context,
122 size_t index,
123 ClassLoaderContext::ClassLoaderType type,
Calin Juravle57d0acc2017-07-11 17:41:30 -0700124 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700125 ASSERT_TRUE(context != nullptr);
126 ASSERT_GT(context->class_loader_chain_.size(), index);
127 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
128 ASSERT_EQ(type, info.type);
129 std::vector<std::string> expected_classpath;
130 Split(classpath, ':', &expected_classpath);
131 ASSERT_EQ(expected_classpath, info.classpath);
132 }
Calin Juravle57d0acc2017-07-11 17:41:30 -0700133
134 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
135 size_t index,
136 ClassLoaderContext::ClassLoaderType type,
137 const std::string& test_name) {
138 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
139 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files;
140 all_dex_files.push_back(&dex_files);
141
142 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
143 VerifyOpenDexFiles(context, index, all_dex_files);
144 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700145};
146
147TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
148 std::unique_ptr<ClassLoaderContext> context =
149 ClassLoaderContext::Create("PCL[a.dex]");
150 VerifyContextSize(context.get(), 1);
151 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
152}
153
154TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
155 std::unique_ptr<ClassLoaderContext> context =
156 ClassLoaderContext::Create("DLC[a.dex]");
157 VerifyContextSize(context.get(), 1);
158 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
159}
160
161TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
162 std::unique_ptr<ClassLoaderContext> context =
163 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
164 VerifyContextSize(context.get(), 3);
165 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
166 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
167 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
168}
169
170TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
171 std::unique_ptr<ClassLoaderContext> context =
172 ClassLoaderContext::Create("DLC[]");
173 VerifyContextSize(context.get(), 1);
174 VerifyClassLoaderDLC(context.get(), 0, "");
175}
176
177TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
178 std::unique_ptr<ClassLoaderContext> context =
179 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
180 VerifyContextSize(context.get(), 0);
181}
182
183TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
184 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
185 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
186 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
187 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
188 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
189 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
190}
191
192TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
193 std::unique_ptr<ClassLoaderContext> context =
194 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
195 VerifyContextSize(context.get(), 1);
196 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
197}
198
199TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
200 std::string multidex_name = GetTestDexFileName("MultiDex");
201 std::vector<std::unique_ptr<const DexFile>> multidex_files = OpenTestDexFiles("MultiDex");
202 std::string myclass_dex_name = GetTestDexFileName("MyClass");
203 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
204 std::string dex_name = GetTestDexFileName("Main");
205 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
206
207
208 std::unique_ptr<ClassLoaderContext> context =
209 ClassLoaderContext::Create(
210 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
211 "DLC[" + dex_name + "]");
212
213 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
214
215 VerifyContextSize(context.get(), 2);
216 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
217 all_dex_files0.push_back(&multidex_files);
218 all_dex_files0.push_back(&myclass_dex_files);
219 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files1;
220 all_dex_files1.push_back(&dex_files);
221
222 VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
223 VerifyOpenDexFiles(context.get(), 1, all_dex_files1);
224}
225
226TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
227 std::string dex_name = GetTestDexFileName("Main");
228 std::unique_ptr<ClassLoaderContext> context =
229 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
230 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
231}
232
233TEST_F(ClassLoaderContextTest, CreateClassLoader) {
234 std::string dex_name = GetTestDexFileName("Main");
235 std::unique_ptr<ClassLoaderContext> context =
236 ClassLoaderContext::Create("PCL[" + dex_name + "]");
237 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
238
239 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
240 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
241
242 std::vector<const DexFile*> compilation_sources_raw =
243 MakeNonOwningPointerVector(compilation_sources);
244 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
245 ASSERT_TRUE(jclass_loader != nullptr);
246
247 ScopedObjectAccess soa(Thread::Current());
248
249 StackHandleScope<2> hs(soa.Self());
250 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
251 soa.Decode<mirror::ClassLoader>(jclass_loader));
252
253 ASSERT_TRUE(class_loader->GetClass() ==
254 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
255 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
256 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
257
258
259 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(jclass_loader);
260 ASSERT_EQ(classpath_dex.size() + compilation_sources.size(), class_loader_dex_files.size());
261
262 // The classpath dex files must come first.
263 for (size_t i = 0; i < classpath_dex.size(); i++) {
264 ASSERT_EQ(classpath_dex[i]->GetLocation(),
265 class_loader_dex_files[i]->GetLocation());
266 ASSERT_EQ(classpath_dex[i]->GetLocationChecksum(),
267 class_loader_dex_files[i]->GetLocationChecksum());
268 }
269
270 // The compilation dex files must come second.
271 for (size_t i = 0, k = classpath_dex.size(); i < compilation_sources.size(); i++, k++) {
272 ASSERT_EQ(compilation_sources[i]->GetLocation(),
273 class_loader_dex_files[k]->GetLocation());
274 ASSERT_EQ(compilation_sources[i]->GetLocationChecksum(),
275 class_loader_dex_files[k]->GetLocationChecksum());
276 }
277}
278
Calin Juravle7b0648a2017-07-07 18:40:50 -0700279TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
280 std::unique_ptr<ClassLoaderContext> context =
281 ClassLoaderContext::Create("");
282 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
283
284 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
285
286 std::vector<const DexFile*> compilation_sources_raw =
287 MakeNonOwningPointerVector(compilation_sources);
288 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
289 ASSERT_TRUE(jclass_loader != nullptr);
290
291 ScopedObjectAccess soa(Thread::Current());
292
293 StackHandleScope<2> hs(soa.Self());
294 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
295 soa.Decode<mirror::ClassLoader>(jclass_loader));
296
297 ASSERT_TRUE(class_loader->GetClass() ==
298 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
299 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
300 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
301
302
303 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(jclass_loader);
304
305 // The compilation sources should be the only files present in the class loader
306 ASSERT_EQ(compilation_sources.size(), class_loader_dex_files.size());
307 for (size_t i = 0; i < compilation_sources.size(); i++) {
308 ASSERT_EQ(compilation_sources[i]->GetLocation(),
309 class_loader_dex_files[i]->GetLocation());
310 ASSERT_EQ(compilation_sources[i]->GetLocationChecksum(),
311 class_loader_dex_files[i]->GetLocationChecksum());
312 }
313}
314
Calin Juravle87e2cb62017-06-13 21:48:45 -0700315TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
316 std::unique_ptr<ClassLoaderContext> context =
317 ClassLoaderContext::Create("PCL[a.dex]");
318 dchecked_vector<std::string> classpath_dex;
319 classpath_dex.push_back("a.dex");
320 dchecked_vector<std::string> compilation_sources;
321 compilation_sources.push_back("src.dex");
322
323 // Nothing should be removed.
324 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
325 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
326 // Classes should be removed.
327 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
328 VerifyClassLoaderPCL(context.get(), 0, "");
329}
330
331TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
332 std::string dex1_name = GetTestDexFileName("Main");
333 std::string dex2_name = GetTestDexFileName("MyClass");
334 std::unique_ptr<ClassLoaderContext> context =
335 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
336 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
337
338 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
339 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
340 std::string encoding = context->EncodeContextForOatFile("");
Calin Juravle7b0648a2017-07-07 18:40:50 -0700341 std::string expected_encoding = "PCL[" +
342 dex1[0]->GetLocation() + "*" + std::to_string(dex1[0]->GetLocationChecksum()) + ":" +
343 dex2[0]->GetLocation() + "*" + std::to_string(dex2[0]->GetLocationChecksum()) + "]";
Calin Juravle87e2cb62017-06-13 21:48:45 -0700344 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
345}
346
Calin Juravle57d0acc2017-07-11 17:41:30 -0700347// TODO(calin) add a test which creates the context for a class loader together with dex_elements.
348TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
349 // The chain is
350 // ClassLoaderA (PathClassLoader)
351 // ^
352 // |
353 // ClassLoaderB (DelegateLastClassLoader)
354 // ^
355 // |
356 // ClassLoaderC (PathClassLoader)
357 // ^
358 // |
359 // ClassLoaderD (DelegateLastClassLoader)
360
361 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
362 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
363 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
364 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
365
366 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
367
368 VerifyContextForClassLoader(context.get());
369 VerifyContextSize(context.get(), 4);
370
371 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
372 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
373 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
374 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
375}
376
Calin Juravle3f918642017-07-11 19:04:20 -0700377TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
378 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
379 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
380
381 VerifyContextSize(context.get(), 2);
382 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
383 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
384
385 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
386
387 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
388 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
389
390 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
391 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
392
393 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
394 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
395
396 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
397 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
398
399 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
400 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
401
402 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
403 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
404
405 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
406 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
407}
408
409TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
410 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
411 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
412 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
413 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
414
415 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
416
417 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
418}
419
Calin Juravle87e2cb62017-06-13 21:48:45 -0700420} // namespace art