blob: e60f61cc11c20a721935a122afbaa7a1f9d03da2 [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 Juravlec79470d2017-07-12 17:37:42 -0700120 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
121 Handle<mirror::ClassLoader> class_loader,
122 jclass type,
123 std::vector<const DexFile*>& expected_dex_files)
124 REQUIRES_SHARED(Locks::mutator_lock_) {
125 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
126
127 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
128 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
129
130 for (size_t i = 0; i < expected_dex_files.size(); i++) {
131 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
132 class_loader_dex_files[i]->GetLocation());
133 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
134 class_loader_dex_files[i]->GetLocationChecksum());
135 }
136 }
137
Calin Juravle87e2cb62017-06-13 21:48:45 -0700138 private:
139 void VerifyClassLoaderInfo(ClassLoaderContext* context,
140 size_t index,
141 ClassLoaderContext::ClassLoaderType type,
Calin Juravle57d0acc2017-07-11 17:41:30 -0700142 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700143 ASSERT_TRUE(context != nullptr);
144 ASSERT_GT(context->class_loader_chain_.size(), index);
145 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
146 ASSERT_EQ(type, info.type);
147 std::vector<std::string> expected_classpath;
148 Split(classpath, ':', &expected_classpath);
149 ASSERT_EQ(expected_classpath, info.classpath);
150 }
Calin Juravle57d0acc2017-07-11 17:41:30 -0700151
152 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
153 size_t index,
154 ClassLoaderContext::ClassLoaderType type,
155 const std::string& test_name) {
156 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
157 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files;
158 all_dex_files.push_back(&dex_files);
159
160 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
161 VerifyOpenDexFiles(context, index, all_dex_files);
162 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700163};
164
Calin Juravle1a509c82017-07-24 16:51:21 -0700165TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
166 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
167 // An empty context should create a single empty PathClassLoader.
168 VerifyContextSize(context.get(), 1);
169 VerifyClassLoaderPCL(context.get(), 0, "");
170}
171
172TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
173 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
174 // An shared library context should have no class loader in the chain.
175 VerifyContextSize(context.get(), 0);
176}
177
Calin Juravle87e2cb62017-06-13 21:48:45 -0700178TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
179 std::unique_ptr<ClassLoaderContext> context =
180 ClassLoaderContext::Create("PCL[a.dex]");
181 VerifyContextSize(context.get(), 1);
182 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
183}
184
185TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
186 std::unique_ptr<ClassLoaderContext> context =
187 ClassLoaderContext::Create("DLC[a.dex]");
188 VerifyContextSize(context.get(), 1);
189 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
190}
191
192TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
193 std::unique_ptr<ClassLoaderContext> context =
194 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
195 VerifyContextSize(context.get(), 3);
196 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
197 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
198 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
199}
200
201TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
202 std::unique_ptr<ClassLoaderContext> context =
203 ClassLoaderContext::Create("DLC[]");
204 VerifyContextSize(context.get(), 1);
205 VerifyClassLoaderDLC(context.get(), 0, "");
206}
207
208TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
209 std::unique_ptr<ClassLoaderContext> context =
210 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
211 VerifyContextSize(context.get(), 0);
212}
213
214TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
215 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
216 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
217 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
218 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
219 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
220 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
221}
222
223TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
224 std::unique_ptr<ClassLoaderContext> context =
225 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
226 VerifyContextSize(context.get(), 1);
227 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
228}
229
230TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
231 std::string multidex_name = GetTestDexFileName("MultiDex");
232 std::vector<std::unique_ptr<const DexFile>> multidex_files = OpenTestDexFiles("MultiDex");
233 std::string myclass_dex_name = GetTestDexFileName("MyClass");
234 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
235 std::string dex_name = GetTestDexFileName("Main");
236 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
237
238
239 std::unique_ptr<ClassLoaderContext> context =
240 ClassLoaderContext::Create(
241 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
242 "DLC[" + dex_name + "]");
243
244 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
245
246 VerifyContextSize(context.get(), 2);
247 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
248 all_dex_files0.push_back(&multidex_files);
249 all_dex_files0.push_back(&myclass_dex_files);
250 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files1;
251 all_dex_files1.push_back(&dex_files);
252
253 VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
254 VerifyOpenDexFiles(context.get(), 1, all_dex_files1);
255}
256
257TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
258 std::string dex_name = GetTestDexFileName("Main");
259 std::unique_ptr<ClassLoaderContext> context =
260 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
261 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
262}
263
264TEST_F(ClassLoaderContextTest, CreateClassLoader) {
265 std::string dex_name = GetTestDexFileName("Main");
266 std::unique_ptr<ClassLoaderContext> context =
267 ClassLoaderContext::Create("PCL[" + dex_name + "]");
268 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
269
270 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
271 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
272
273 std::vector<const DexFile*> compilation_sources_raw =
274 MakeNonOwningPointerVector(compilation_sources);
275 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
276 ASSERT_TRUE(jclass_loader != nullptr);
277
278 ScopedObjectAccess soa(Thread::Current());
279
Calin Juravlec79470d2017-07-12 17:37:42 -0700280 StackHandleScope<1> hs(soa.Self());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700281 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
282 soa.Decode<mirror::ClassLoader>(jclass_loader));
283
284 ASSERT_TRUE(class_loader->GetClass() ==
285 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
286 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
287 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
288
Calin Juravlec79470d2017-07-12 17:37:42 -0700289 // For the first class loader the class path dex files must come first and then the
290 // compilation sources.
291 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
292 for (auto& dex : compilation_sources_raw) {
293 expected_classpath.push_back(dex);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700294 }
295
Calin Juravlec79470d2017-07-12 17:37:42 -0700296 VerifyClassLoaderDexFiles(soa,
297 class_loader,
298 WellKnownClasses::dalvik_system_PathClassLoader,
299 expected_classpath);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700300}
301
Calin Juravle7b0648a2017-07-07 18:40:50 -0700302TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
303 std::unique_ptr<ClassLoaderContext> context =
304 ClassLoaderContext::Create("");
305 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
306
307 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
308
309 std::vector<const DexFile*> compilation_sources_raw =
310 MakeNonOwningPointerVector(compilation_sources);
311 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
312 ASSERT_TRUE(jclass_loader != nullptr);
313
314 ScopedObjectAccess soa(Thread::Current());
315
Calin Juravlec79470d2017-07-12 17:37:42 -0700316 StackHandleScope<1> hs(soa.Self());
Calin Juravle7b0648a2017-07-07 18:40:50 -0700317 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
318 soa.Decode<mirror::ClassLoader>(jclass_loader));
319
Calin Juravlec79470d2017-07-12 17:37:42 -0700320 // An empty context should create a single PathClassLoader with only the compilation sources.
321 VerifyClassLoaderDexFiles(soa,
322 class_loader,
323 WellKnownClasses::dalvik_system_PathClassLoader,
324 compilation_sources_raw);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700325 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
326 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700327}
328
Calin Juravle1a509c82017-07-24 16:51:21 -0700329TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
330 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
331
332 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
333
334 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
335
336 std::vector<const DexFile*> compilation_sources_raw =
337 MakeNonOwningPointerVector(compilation_sources);
338 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
339 ASSERT_TRUE(jclass_loader != nullptr);
340
341 ScopedObjectAccess soa(Thread::Current());
342
343 StackHandleScope<1> hs(soa.Self());
344 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
345 soa.Decode<mirror::ClassLoader>(jclass_loader));
346
347 // A shared library context should create a single PathClassLoader with only the compilation
348 // sources.
349 VerifyClassLoaderDexFiles(soa,
350 class_loader,
351 WellKnownClasses::dalvik_system_PathClassLoader,
352 compilation_sources_raw);
353 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
354 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
355}
356
Calin Juravlec79470d2017-07-12 17:37:42 -0700357TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
358 // Setup the context.
359 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
360 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
361 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
362 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
363
364 std::string context_spec =
365 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
366 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
367 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
368
369 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
370 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
371
372 // Setup the compilation sources.
373 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
374 std::vector<const DexFile*> compilation_sources_raw =
375 MakeNonOwningPointerVector(compilation_sources);
376
377 // Create the class loader.
378 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
379 ASSERT_TRUE(jclass_loader != nullptr);
380
381 // Verify the class loader.
382 ScopedObjectAccess soa(Thread::Current());
383
384 StackHandleScope<3> hs(soa.Self());
385 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
386 soa.Decode<mirror::ClassLoader>(jclass_loader));
387
388 // Verify the first class loader
389
390 // For the first class loader the class path dex files must come first and then the
391 // compilation sources.
392 std::vector<const DexFile*> class_loader_1_dex_files =
393 MakeNonOwningPointerVector(classpath_dex_a);
394 for (auto& dex : classpath_dex_b) {
395 class_loader_1_dex_files.push_back(dex.get());
396 }
397 for (auto& dex : compilation_sources_raw) {
398 class_loader_1_dex_files.push_back(dex);
399 }
400 VerifyClassLoaderDexFiles(soa,
401 class_loader_1,
402 WellKnownClasses::dalvik_system_PathClassLoader,
403 class_loader_1_dex_files);
404
405 // Verify the second class loader
406 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
407 std::vector<const DexFile*> class_loader_2_dex_files =
408 MakeNonOwningPointerVector(classpath_dex_c);
409 VerifyClassLoaderDexFiles(soa,
410 class_loader_2,
411 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
412 class_loader_2_dex_files);
413
414 // Verify the third class loader
415 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
416 std::vector<const DexFile*> class_loader_3_dex_files =
417 MakeNonOwningPointerVector(classpath_dex_d);
418 VerifyClassLoaderDexFiles(soa,
419 class_loader_3,
420 WellKnownClasses::dalvik_system_PathClassLoader,
421 class_loader_3_dex_files);
422 // The last class loader should have the BootClassLoader as a parent.
423 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
424 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
425}
426
427
Calin Juravle87e2cb62017-06-13 21:48:45 -0700428TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
429 std::unique_ptr<ClassLoaderContext> context =
430 ClassLoaderContext::Create("PCL[a.dex]");
431 dchecked_vector<std::string> classpath_dex;
432 classpath_dex.push_back("a.dex");
433 dchecked_vector<std::string> compilation_sources;
434 compilation_sources.push_back("src.dex");
435
436 // Nothing should be removed.
437 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
438 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
439 // Classes should be removed.
440 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
441 VerifyClassLoaderPCL(context.get(), 0, "");
442}
443
444TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
445 std::string dex1_name = GetTestDexFileName("Main");
446 std::string dex2_name = GetTestDexFileName("MyClass");
447 std::unique_ptr<ClassLoaderContext> context =
448 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
449 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
450
451 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
452 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
453 std::string encoding = context->EncodeContextForOatFile("");
Calin Juravlec79470d2017-07-12 17:37:42 -0700454 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
455 CreateClassPathWithChecksums(dex2) + "]";
Calin Juravle87e2cb62017-06-13 21:48:45 -0700456 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
457}
458
Calin Juravle57d0acc2017-07-11 17:41:30 -0700459// TODO(calin) add a test which creates the context for a class loader together with dex_elements.
460TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
461 // The chain is
462 // ClassLoaderA (PathClassLoader)
463 // ^
464 // |
465 // ClassLoaderB (DelegateLastClassLoader)
466 // ^
467 // |
468 // ClassLoaderC (PathClassLoader)
469 // ^
470 // |
471 // ClassLoaderD (DelegateLastClassLoader)
472
473 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
474 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
475 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
476 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
477
478 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
479
480 VerifyContextForClassLoader(context.get());
481 VerifyContextSize(context.get(), 4);
482
483 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
484 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
485 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
486 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
487}
488
Calin Juravle3f918642017-07-11 19:04:20 -0700489TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
490 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
491 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
492
493 VerifyContextSize(context.get(), 2);
494 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
495 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
496
497 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
498
499 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
500 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
501
502 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
503 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
504
505 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
506 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
507
508 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
509 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
510
511 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
512 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
513
514 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
515 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
516
517 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
518 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
519}
520
521TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
522 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
523 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
524 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
525 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
526
527 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
528
529 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
530}
531
Calin Juravle87e2cb62017-06-13 21:48:45 -0700532} // namespace art