blob: d4688c1904c27b627d25e83e3c2d0163c5400e9b [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
Calin Juravle87e2cb62017-06-13 21:48:45 -070019#include "class_loader_context.h"
20#include "common_runtime_test.h"
21
22#include "base/dchecked_vector.h"
23#include "base/stl_util.h"
24#include "class_linker.h"
25#include "dex_file.h"
26#include "handle_scope-inl.h"
27#include "mirror/class.h"
28#include "mirror/class_loader.h"
29#include "mirror/object-inl.h"
30#include "oat_file_assistant.h"
31#include "runtime.h"
32#include "scoped_thread_state_change-inl.h"
33#include "thread.h"
34#include "well_known_classes.h"
35
36namespace art {
37
38class ClassLoaderContextTest : public CommonRuntimeTest {
39 public:
40 void VerifyContextSize(ClassLoaderContext* context, size_t expected_size) {
41 ASSERT_TRUE(context != nullptr);
42 ASSERT_EQ(expected_size, context->class_loader_chain_.size());
43 }
44
45 void VerifyClassLoaderPCL(ClassLoaderContext* context,
46 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070047 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070048 VerifyClassLoaderInfo(
49 context, index, ClassLoaderContext::kPathClassLoader, classpath);
50 }
51
52 void VerifyClassLoaderDLC(ClassLoaderContext* context,
53 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070054 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070055 VerifyClassLoaderInfo(
56 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath);
57 }
58
Calin Juravle57d0acc2017-07-11 17:41:30 -070059 void VerifyClassLoaderPCLFromTestDex(ClassLoaderContext* context,
60 size_t index,
61 const std::string& test_name) {
62 VerifyClassLoaderFromTestDex(
63 context, index, ClassLoaderContext::kPathClassLoader, test_name);
64 }
65
66 void VerifyClassLoaderDLCFromTestDex(ClassLoaderContext* context,
67 size_t index,
68 const std::string& test_name) {
69 VerifyClassLoaderFromTestDex(
70 context, index, ClassLoaderContext::kDelegateLastClassLoader, test_name);
71 }
72
Calin Juravle87e2cb62017-06-13 21:48:45 -070073 void VerifyOpenDexFiles(
74 ClassLoaderContext* context,
75 size_t index,
76 std::vector<std::vector<std::unique_ptr<const DexFile>>*>& all_dex_files) {
77 ASSERT_TRUE(context != nullptr);
78 ASSERT_TRUE(context->dex_files_open_attempted_);
79 ASSERT_TRUE(context->dex_files_open_result_);
80 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
81 ASSERT_EQ(all_dex_files.size(), info.classpath.size());
82 size_t cur_open_dex_index = 0;
83 for (size_t k = 0; k < all_dex_files.size(); k++) {
84 std::vector<std::unique_ptr<const DexFile>>& dex_files_for_cp_elem = *(all_dex_files[k]);
85 for (size_t i = 0; i < dex_files_for_cp_elem.size(); i++) {
86 ASSERT_LT(cur_open_dex_index, info.opened_dex_files.size());
87
88 std::unique_ptr<const DexFile>& opened_dex_file =
89 info.opened_dex_files[cur_open_dex_index++];
90 std::unique_ptr<const DexFile>& expected_dex_file = dex_files_for_cp_elem[i];
91
92 ASSERT_EQ(expected_dex_file->GetLocation(), opened_dex_file->GetLocation());
93 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
94 ASSERT_EQ(info.classpath[k], opened_dex_file->GetBaseLocation());
95 }
96 }
97 }
98
Calin Juravle57d0acc2017-07-11 17:41:30 -070099 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
100 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
101 }
102
Calin Juravle3f918642017-07-11 19:04:20 -0700103 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
104 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
105 if (!context->Parse(context_spec, /*parse_checksums*/ true)) {
106 return nullptr;
107 }
108 return context;
109 }
110
Calin Juravle57d0acc2017-07-11 17:41:30 -0700111 void VerifyContextForClassLoader(ClassLoaderContext* context) {
112 ASSERT_TRUE(context != nullptr);
113 ASSERT_TRUE(context->dex_files_open_attempted_);
114 ASSERT_TRUE(context->dex_files_open_result_);
115 ASSERT_FALSE(context->owns_the_dex_files_);
116 ASSERT_FALSE(context->special_shared_library_);
117 }
118
Calin Juravlec79470d2017-07-12 17:37:42 -0700119 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
120 Handle<mirror::ClassLoader> class_loader,
121 jclass type,
122 std::vector<const DexFile*>& expected_dex_files)
123 REQUIRES_SHARED(Locks::mutator_lock_) {
124 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
125
126 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
127 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
128
129 for (size_t i = 0; i < expected_dex_files.size(); i++) {
130 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
131 class_loader_dex_files[i]->GetLocation());
132 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
133 class_loader_dex_files[i]->GetLocationChecksum());
134 }
135 }
136
Calin Juravle87e2cb62017-06-13 21:48:45 -0700137 private:
138 void VerifyClassLoaderInfo(ClassLoaderContext* context,
139 size_t index,
140 ClassLoaderContext::ClassLoaderType type,
Calin Juravle57d0acc2017-07-11 17:41:30 -0700141 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700142 ASSERT_TRUE(context != nullptr);
143 ASSERT_GT(context->class_loader_chain_.size(), index);
144 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
145 ASSERT_EQ(type, info.type);
146 std::vector<std::string> expected_classpath;
147 Split(classpath, ':', &expected_classpath);
148 ASSERT_EQ(expected_classpath, info.classpath);
149 }
Calin Juravle57d0acc2017-07-11 17:41:30 -0700150
151 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
152 size_t index,
153 ClassLoaderContext::ClassLoaderType type,
154 const std::string& test_name) {
155 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
156 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files;
157 all_dex_files.push_back(&dex_files);
158
159 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
160 VerifyOpenDexFiles(context, index, all_dex_files);
161 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700162};
163
Calin Juravle1a509c82017-07-24 16:51:21 -0700164TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
165 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
166 // An empty context should create a single empty PathClassLoader.
167 VerifyContextSize(context.get(), 1);
168 VerifyClassLoaderPCL(context.get(), 0, "");
169}
170
171TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
172 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
173 // An shared library context should have no class loader in the chain.
174 VerifyContextSize(context.get(), 0);
175}
176
Calin Juravle87e2cb62017-06-13 21:48:45 -0700177TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
178 std::unique_ptr<ClassLoaderContext> context =
179 ClassLoaderContext::Create("PCL[a.dex]");
180 VerifyContextSize(context.get(), 1);
181 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
182}
183
184TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
185 std::unique_ptr<ClassLoaderContext> context =
186 ClassLoaderContext::Create("DLC[a.dex]");
187 VerifyContextSize(context.get(), 1);
188 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
189}
190
191TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
192 std::unique_ptr<ClassLoaderContext> context =
193 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
194 VerifyContextSize(context.get(), 3);
195 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
196 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
197 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
198}
199
200TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
201 std::unique_ptr<ClassLoaderContext> context =
202 ClassLoaderContext::Create("DLC[]");
203 VerifyContextSize(context.get(), 1);
204 VerifyClassLoaderDLC(context.get(), 0, "");
205}
206
207TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
208 std::unique_ptr<ClassLoaderContext> context =
209 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
210 VerifyContextSize(context.get(), 0);
211}
212
213TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
214 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
215 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
216 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
217 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
218 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
219 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
220}
221
222TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
223 std::unique_ptr<ClassLoaderContext> context =
224 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
225 VerifyContextSize(context.get(), 1);
226 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
227}
228
229TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
230 std::string multidex_name = GetTestDexFileName("MultiDex");
231 std::vector<std::unique_ptr<const DexFile>> multidex_files = OpenTestDexFiles("MultiDex");
232 std::string myclass_dex_name = GetTestDexFileName("MyClass");
233 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
234 std::string dex_name = GetTestDexFileName("Main");
235 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
236
237
238 std::unique_ptr<ClassLoaderContext> context =
239 ClassLoaderContext::Create(
240 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
241 "DLC[" + dex_name + "]");
242
243 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
244
245 VerifyContextSize(context.get(), 2);
246 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
247 all_dex_files0.push_back(&multidex_files);
248 all_dex_files0.push_back(&myclass_dex_files);
249 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files1;
250 all_dex_files1.push_back(&dex_files);
251
252 VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
253 VerifyOpenDexFiles(context.get(), 1, all_dex_files1);
254}
255
256TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
257 std::string dex_name = GetTestDexFileName("Main");
258 std::unique_ptr<ClassLoaderContext> context =
259 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
260 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
261}
262
263TEST_F(ClassLoaderContextTest, CreateClassLoader) {
264 std::string dex_name = GetTestDexFileName("Main");
265 std::unique_ptr<ClassLoaderContext> context =
266 ClassLoaderContext::Create("PCL[" + dex_name + "]");
267 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
268
269 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
270 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
271
272 std::vector<const DexFile*> compilation_sources_raw =
273 MakeNonOwningPointerVector(compilation_sources);
274 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
275 ASSERT_TRUE(jclass_loader != nullptr);
276
277 ScopedObjectAccess soa(Thread::Current());
278
Calin Juravlec79470d2017-07-12 17:37:42 -0700279 StackHandleScope<1> hs(soa.Self());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700280 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
281 soa.Decode<mirror::ClassLoader>(jclass_loader));
282
283 ASSERT_TRUE(class_loader->GetClass() ==
284 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
285 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
286 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
287
Calin Juravlec79470d2017-07-12 17:37:42 -0700288 // For the first class loader the class path dex files must come first and then the
289 // compilation sources.
290 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
291 for (auto& dex : compilation_sources_raw) {
292 expected_classpath.push_back(dex);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700293 }
294
Calin Juravlec79470d2017-07-12 17:37:42 -0700295 VerifyClassLoaderDexFiles(soa,
296 class_loader,
297 WellKnownClasses::dalvik_system_PathClassLoader,
298 expected_classpath);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700299}
300
Calin Juravle7b0648a2017-07-07 18:40:50 -0700301TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
302 std::unique_ptr<ClassLoaderContext> context =
303 ClassLoaderContext::Create("");
304 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
305
306 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
307
308 std::vector<const DexFile*> compilation_sources_raw =
309 MakeNonOwningPointerVector(compilation_sources);
310 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
311 ASSERT_TRUE(jclass_loader != nullptr);
312
313 ScopedObjectAccess soa(Thread::Current());
314
Calin Juravlec79470d2017-07-12 17:37:42 -0700315 StackHandleScope<1> hs(soa.Self());
Calin Juravle7b0648a2017-07-07 18:40:50 -0700316 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
317 soa.Decode<mirror::ClassLoader>(jclass_loader));
318
Calin Juravlec79470d2017-07-12 17:37:42 -0700319 // An empty context should create a single PathClassLoader with only the compilation sources.
320 VerifyClassLoaderDexFiles(soa,
321 class_loader,
322 WellKnownClasses::dalvik_system_PathClassLoader,
323 compilation_sources_raw);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700324 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
325 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700326}
327
Calin Juravle1a509c82017-07-24 16:51:21 -0700328TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
329 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
330
331 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
332
333 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
334
335 std::vector<const DexFile*> compilation_sources_raw =
336 MakeNonOwningPointerVector(compilation_sources);
337 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
338 ASSERT_TRUE(jclass_loader != nullptr);
339
340 ScopedObjectAccess soa(Thread::Current());
341
342 StackHandleScope<1> hs(soa.Self());
343 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
344 soa.Decode<mirror::ClassLoader>(jclass_loader));
345
346 // A shared library context should create a single PathClassLoader with only the compilation
347 // sources.
348 VerifyClassLoaderDexFiles(soa,
349 class_loader,
350 WellKnownClasses::dalvik_system_PathClassLoader,
351 compilation_sources_raw);
352 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
353 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
354}
355
Calin Juravlec79470d2017-07-12 17:37:42 -0700356TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
357 // Setup the context.
358 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
359 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
360 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
361 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
362
363 std::string context_spec =
364 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
365 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
366 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
367
368 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
369 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
370
371 // Setup the compilation sources.
372 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
373 std::vector<const DexFile*> compilation_sources_raw =
374 MakeNonOwningPointerVector(compilation_sources);
375
376 // Create the class loader.
377 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
378 ASSERT_TRUE(jclass_loader != nullptr);
379
380 // Verify the class loader.
381 ScopedObjectAccess soa(Thread::Current());
382
383 StackHandleScope<3> hs(soa.Self());
384 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
385 soa.Decode<mirror::ClassLoader>(jclass_loader));
386
387 // Verify the first class loader
388
389 // For the first class loader the class path dex files must come first and then the
390 // compilation sources.
391 std::vector<const DexFile*> class_loader_1_dex_files =
392 MakeNonOwningPointerVector(classpath_dex_a);
393 for (auto& dex : classpath_dex_b) {
394 class_loader_1_dex_files.push_back(dex.get());
395 }
396 for (auto& dex : compilation_sources_raw) {
397 class_loader_1_dex_files.push_back(dex);
398 }
399 VerifyClassLoaderDexFiles(soa,
400 class_loader_1,
401 WellKnownClasses::dalvik_system_PathClassLoader,
402 class_loader_1_dex_files);
403
404 // Verify the second class loader
405 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
406 std::vector<const DexFile*> class_loader_2_dex_files =
407 MakeNonOwningPointerVector(classpath_dex_c);
408 VerifyClassLoaderDexFiles(soa,
409 class_loader_2,
410 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
411 class_loader_2_dex_files);
412
413 // Verify the third class loader
414 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
415 std::vector<const DexFile*> class_loader_3_dex_files =
416 MakeNonOwningPointerVector(classpath_dex_d);
417 VerifyClassLoaderDexFiles(soa,
418 class_loader_3,
419 WellKnownClasses::dalvik_system_PathClassLoader,
420 class_loader_3_dex_files);
421 // The last class loader should have the BootClassLoader as a parent.
422 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
423 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
424}
425
426
Calin Juravle87e2cb62017-06-13 21:48:45 -0700427TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
428 std::unique_ptr<ClassLoaderContext> context =
429 ClassLoaderContext::Create("PCL[a.dex]");
430 dchecked_vector<std::string> classpath_dex;
431 classpath_dex.push_back("a.dex");
432 dchecked_vector<std::string> compilation_sources;
433 compilation_sources.push_back("src.dex");
434
435 // Nothing should be removed.
436 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
437 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
438 // Classes should be removed.
439 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
440 VerifyClassLoaderPCL(context.get(), 0, "");
441}
442
443TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
444 std::string dex1_name = GetTestDexFileName("Main");
445 std::string dex2_name = GetTestDexFileName("MyClass");
446 std::unique_ptr<ClassLoaderContext> context =
447 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
448 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
449
450 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
451 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
452 std::string encoding = context->EncodeContextForOatFile("");
Calin Juravlec79470d2017-07-12 17:37:42 -0700453 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
454 CreateClassPathWithChecksums(dex2) + "]";
Calin Juravle87e2cb62017-06-13 21:48:45 -0700455 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
456}
457
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700458TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
459 std::string dex1_name = GetTestDexFileName("Main");
460 std::string dex2_name = GetTestDexFileName("MultiDex");
461 std::unique_ptr<ClassLoaderContext> context =
462 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
463 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
464
465 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
466 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MultiDex");
467 std::string encoding = context->EncodeContextForDex2oat("");
468 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
469 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
470}
471
Calin Juravle57d0acc2017-07-11 17:41:30 -0700472// TODO(calin) add a test which creates the context for a class loader together with dex_elements.
473TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
474 // The chain is
475 // ClassLoaderA (PathClassLoader)
476 // ^
477 // |
478 // ClassLoaderB (DelegateLastClassLoader)
479 // ^
480 // |
481 // ClassLoaderC (PathClassLoader)
482 // ^
483 // |
484 // ClassLoaderD (DelegateLastClassLoader)
485
486 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
487 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
488 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
489 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
490
491 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
492
493 VerifyContextForClassLoader(context.get());
494 VerifyContextSize(context.get(), 4);
495
496 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
497 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
498 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
499 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
500}
501
Calin Juravle3f918642017-07-11 19:04:20 -0700502TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
503 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
504 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
505
506 VerifyContextSize(context.get(), 2);
507 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
508 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
509
510 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
511
512 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
513 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
514
515 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
516 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
517
518 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
519 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
520
521 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
522 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
523
524 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
525 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
526
527 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
528 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
529
530 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
531 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
532}
533
534TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
535 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
536 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
537 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
538 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
539
540 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
541
542 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
543}
544
Calin Juravlea308a322017-07-18 16:51:51 -0700545TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
546 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
547
548 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
549
550 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
551}
552
Calin Juravle87e2cb62017-06-13 21:48:45 -0700553} // namespace art