blob: 458f9f3345a1922e199448e4bce2edb7e39bfd02 [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>
Calin Juravle821a2592017-08-11 14:33:38 -070018#include <stdlib.h>
Calin Juravle87e2cb62017-06-13 21:48:45 -070019
Calin Juravle87e2cb62017-06-13 21:48:45 -070020
21#include "base/dchecked_vector.h"
22#include "base/stl_util.h"
Calin Juravle821a2592017-08-11 14:33:38 -070023#include "class_loader_context.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070024#include "class_linker.h"
Calin Juravle821a2592017-08-11 14:33:38 -070025#include "common_runtime_test.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070026#include "dex_file.h"
Calin Juravle821a2592017-08-11 14:33:38 -070027#include "dex2oat_environment_test.h"
Calin Juravle87e2cb62017-06-13 21:48:45 -070028#include "handle_scope-inl.h"
29#include "mirror/class.h"
30#include "mirror/class_loader.h"
31#include "mirror/object-inl.h"
32#include "oat_file_assistant.h"
33#include "runtime.h"
34#include "scoped_thread_state_change-inl.h"
35#include "thread.h"
36#include "well_known_classes.h"
37
38namespace art {
39
40class ClassLoaderContextTest : public CommonRuntimeTest {
41 public:
42 void VerifyContextSize(ClassLoaderContext* context, size_t expected_size) {
43 ASSERT_TRUE(context != nullptr);
44 ASSERT_EQ(expected_size, context->class_loader_chain_.size());
45 }
46
47 void VerifyClassLoaderPCL(ClassLoaderContext* context,
48 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070049 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070050 VerifyClassLoaderInfo(
51 context, index, ClassLoaderContext::kPathClassLoader, classpath);
52 }
53
54 void VerifyClassLoaderDLC(ClassLoaderContext* context,
55 size_t index,
Calin Juravle57d0acc2017-07-11 17:41:30 -070056 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -070057 VerifyClassLoaderInfo(
58 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath);
59 }
60
Calin Juravle57d0acc2017-07-11 17:41:30 -070061 void VerifyClassLoaderPCLFromTestDex(ClassLoaderContext* context,
62 size_t index,
63 const std::string& test_name) {
64 VerifyClassLoaderFromTestDex(
65 context, index, ClassLoaderContext::kPathClassLoader, test_name);
66 }
67
68 void VerifyClassLoaderDLCFromTestDex(ClassLoaderContext* context,
69 size_t index,
70 const std::string& test_name) {
71 VerifyClassLoaderFromTestDex(
72 context, index, ClassLoaderContext::kDelegateLastClassLoader, test_name);
73 }
74
Calin Juravle87e2cb62017-06-13 21:48:45 -070075 void VerifyOpenDexFiles(
76 ClassLoaderContext* context,
77 size_t index,
78 std::vector<std::vector<std::unique_ptr<const DexFile>>*>& all_dex_files) {
79 ASSERT_TRUE(context != nullptr);
80 ASSERT_TRUE(context->dex_files_open_attempted_);
81 ASSERT_TRUE(context->dex_files_open_result_);
82 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
83 ASSERT_EQ(all_dex_files.size(), info.classpath.size());
84 size_t cur_open_dex_index = 0;
85 for (size_t k = 0; k < all_dex_files.size(); k++) {
86 std::vector<std::unique_ptr<const DexFile>>& dex_files_for_cp_elem = *(all_dex_files[k]);
87 for (size_t i = 0; i < dex_files_for_cp_elem.size(); i++) {
88 ASSERT_LT(cur_open_dex_index, info.opened_dex_files.size());
89
90 std::unique_ptr<const DexFile>& opened_dex_file =
91 info.opened_dex_files[cur_open_dex_index++];
92 std::unique_ptr<const DexFile>& expected_dex_file = dex_files_for_cp_elem[i];
93
Calin Juravle821a2592017-08-11 14:33:38 -070094 std::string expected_location = expected_dex_file->GetBaseLocation();
95 UniqueCPtr<const char[]> expected_real_location(
96 realpath(expected_location.c_str(), nullptr));
97 ASSERT_TRUE(expected_real_location != nullptr) << expected_location;
98 expected_location.assign(expected_real_location.get());
99 expected_location += DexFile::GetMultiDexSuffix(expected_dex_file->GetLocation());
100
101 ASSERT_EQ(expected_location, opened_dex_file->GetLocation());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700102 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
Calin Juravle821a2592017-08-11 14:33:38 -0700103
104 std::string class_path_location = info.classpath[k];
105 UniqueCPtr<const char[]> class_path_location_real(
106 realpath(class_path_location.c_str(), nullptr));
107 ASSERT_TRUE(class_path_location_real != nullptr);
108 class_path_location.assign(class_path_location_real.get());
109 ASSERT_EQ(class_path_location, opened_dex_file->GetBaseLocation());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700110 }
111 }
112 }
113
Calin Juravle57d0acc2017-07-11 17:41:30 -0700114 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
115 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
116 }
117
Calin Juravle3f918642017-07-11 19:04:20 -0700118 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
119 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
120 if (!context->Parse(context_spec, /*parse_checksums*/ true)) {
121 return nullptr;
122 }
123 return context;
124 }
125
Calin Juravle57d0acc2017-07-11 17:41:30 -0700126 void VerifyContextForClassLoader(ClassLoaderContext* context) {
127 ASSERT_TRUE(context != nullptr);
128 ASSERT_TRUE(context->dex_files_open_attempted_);
129 ASSERT_TRUE(context->dex_files_open_result_);
130 ASSERT_FALSE(context->owns_the_dex_files_);
131 ASSERT_FALSE(context->special_shared_library_);
132 }
133
Calin Juravlec79470d2017-07-12 17:37:42 -0700134 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
135 Handle<mirror::ClassLoader> class_loader,
136 jclass type,
137 std::vector<const DexFile*>& expected_dex_files)
138 REQUIRES_SHARED(Locks::mutator_lock_) {
139 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
140
141 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
142 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
143
144 for (size_t i = 0; i < expected_dex_files.size(); i++) {
145 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
146 class_loader_dex_files[i]->GetLocation());
147 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
148 class_loader_dex_files[i]->GetLocationChecksum());
149 }
150 }
151
Calin Juravle87e2cb62017-06-13 21:48:45 -0700152 private:
153 void VerifyClassLoaderInfo(ClassLoaderContext* context,
154 size_t index,
155 ClassLoaderContext::ClassLoaderType type,
Calin Juravle57d0acc2017-07-11 17:41:30 -0700156 const std::string& classpath) {
Calin Juravle87e2cb62017-06-13 21:48:45 -0700157 ASSERT_TRUE(context != nullptr);
158 ASSERT_GT(context->class_loader_chain_.size(), index);
159 ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
160 ASSERT_EQ(type, info.type);
161 std::vector<std::string> expected_classpath;
162 Split(classpath, ':', &expected_classpath);
163 ASSERT_EQ(expected_classpath, info.classpath);
164 }
Calin Juravle57d0acc2017-07-11 17:41:30 -0700165
166 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
167 size_t index,
168 ClassLoaderContext::ClassLoaderType type,
169 const std::string& test_name) {
170 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
171 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files;
172 all_dex_files.push_back(&dex_files);
173
174 VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
175 VerifyOpenDexFiles(context, index, all_dex_files);
176 }
Calin Juravle87e2cb62017-06-13 21:48:45 -0700177};
178
Calin Juravle1a509c82017-07-24 16:51:21 -0700179TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
180 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
181 // An empty context should create a single empty PathClassLoader.
182 VerifyContextSize(context.get(), 1);
183 VerifyClassLoaderPCL(context.get(), 0, "");
184}
185
186TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
187 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
188 // An shared library context should have no class loader in the chain.
189 VerifyContextSize(context.get(), 0);
190}
191
Calin Juravle87e2cb62017-06-13 21:48:45 -0700192TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
193 std::unique_ptr<ClassLoaderContext> context =
194 ClassLoaderContext::Create("PCL[a.dex]");
195 VerifyContextSize(context.get(), 1);
196 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
197}
198
199TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
200 std::unique_ptr<ClassLoaderContext> context =
201 ClassLoaderContext::Create("DLC[a.dex]");
202 VerifyContextSize(context.get(), 1);
203 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
204}
205
206TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
207 std::unique_ptr<ClassLoaderContext> context =
208 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
209 VerifyContextSize(context.get(), 3);
210 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
211 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
212 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
213}
214
215TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
216 std::unique_ptr<ClassLoaderContext> context =
217 ClassLoaderContext::Create("DLC[]");
218 VerifyContextSize(context.get(), 1);
219 VerifyClassLoaderDLC(context.get(), 0, "");
220}
221
222TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
223 std::unique_ptr<ClassLoaderContext> context =
224 ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
225 VerifyContextSize(context.get(), 0);
226}
227
228TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
229 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
230 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
231 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
232 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
233 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
234 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
235}
236
237TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
238 std::unique_ptr<ClassLoaderContext> context =
239 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
240 VerifyContextSize(context.get(), 1);
241 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
242}
243
244TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
245 std::string multidex_name = GetTestDexFileName("MultiDex");
246 std::vector<std::unique_ptr<const DexFile>> multidex_files = OpenTestDexFiles("MultiDex");
247 std::string myclass_dex_name = GetTestDexFileName("MyClass");
248 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
249 std::string dex_name = GetTestDexFileName("Main");
250 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("Main");
251
Calin Juravle87e2cb62017-06-13 21:48:45 -0700252 std::unique_ptr<ClassLoaderContext> context =
253 ClassLoaderContext::Create(
254 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
255 "DLC[" + dex_name + "]");
256
257 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
258
259 VerifyContextSize(context.get(), 2);
260 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
261 all_dex_files0.push_back(&multidex_files);
262 all_dex_files0.push_back(&myclass_dex_files);
263 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files1;
264 all_dex_files1.push_back(&dex_files);
265
266 VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
267 VerifyOpenDexFiles(context.get(), 1, all_dex_files1);
268}
269
Calin Juravle821a2592017-08-11 14:33:38 -0700270class ScratchSymLink {
271 public:
272 explicit ScratchSymLink(const std::string& file) {
273 // Use a temporary scratch file to get a unique name for the link.
274 ScratchFile scratchFile;
275 scratch_link_name_ = scratchFile.GetFilename() + ".link.jar";
276 CHECK_EQ(0, symlink(file.c_str(), scratch_link_name_.c_str()));
277 }
278
279 ~ScratchSymLink() {
280 CHECK_EQ(0, unlink(scratch_link_name_.c_str()));
281 }
282
283 const std::string& GetFilename() { return scratch_link_name_; }
284
285 private:
286 std::string scratch_link_name_;
287};
288
289TEST_F(ClassLoaderContextTest, OpenValidDexFilesSymLink) {
290 std::string myclass_dex_name = GetTestDexFileName("MyClass");
291 // Now replace the dex location with a symlink.
292 ScratchSymLink link(myclass_dex_name);
293
294 std::unique_ptr<ClassLoaderContext> context =
295 ClassLoaderContext::Create("PCL[" + link.GetFilename() + "]");
296
297 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
298
299 VerifyContextSize(context.get(), 1);
300 std::vector<std::vector<std::unique_ptr<const DexFile>>*> all_dex_files0;
301 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
302 all_dex_files0.push_back(&myclass_dex_files);
303
304 VerifyOpenDexFiles(context.get(), 0, all_dex_files0);
305}
306
Calin Juravle87e2cb62017-06-13 21:48:45 -0700307TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
308 std::string dex_name = GetTestDexFileName("Main");
309 std::unique_ptr<ClassLoaderContext> context =
310 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
311 ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
312}
313
314TEST_F(ClassLoaderContextTest, CreateClassLoader) {
315 std::string dex_name = GetTestDexFileName("Main");
316 std::unique_ptr<ClassLoaderContext> context =
317 ClassLoaderContext::Create("PCL[" + dex_name + "]");
318 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
319
320 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
321 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
322
323 std::vector<const DexFile*> compilation_sources_raw =
324 MakeNonOwningPointerVector(compilation_sources);
325 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
326 ASSERT_TRUE(jclass_loader != nullptr);
327
328 ScopedObjectAccess soa(Thread::Current());
329
Calin Juravlec79470d2017-07-12 17:37:42 -0700330 StackHandleScope<1> hs(soa.Self());
Calin Juravle87e2cb62017-06-13 21:48:45 -0700331 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
332 soa.Decode<mirror::ClassLoader>(jclass_loader));
333
334 ASSERT_TRUE(class_loader->GetClass() ==
335 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
336 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
337 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
338
Calin Juravlec79470d2017-07-12 17:37:42 -0700339 // For the first class loader the class path dex files must come first and then the
340 // compilation sources.
341 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
342 for (auto& dex : compilation_sources_raw) {
343 expected_classpath.push_back(dex);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700344 }
345
Calin Juravlec79470d2017-07-12 17:37:42 -0700346 VerifyClassLoaderDexFiles(soa,
347 class_loader,
348 WellKnownClasses::dalvik_system_PathClassLoader,
349 expected_classpath);
Calin Juravle87e2cb62017-06-13 21:48:45 -0700350}
351
Calin Juravle7b0648a2017-07-07 18:40:50 -0700352TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
353 std::unique_ptr<ClassLoaderContext> context =
354 ClassLoaderContext::Create("");
355 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
356
357 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
358
359 std::vector<const DexFile*> compilation_sources_raw =
360 MakeNonOwningPointerVector(compilation_sources);
361 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
362 ASSERT_TRUE(jclass_loader != nullptr);
363
364 ScopedObjectAccess soa(Thread::Current());
365
Calin Juravlec79470d2017-07-12 17:37:42 -0700366 StackHandleScope<1> hs(soa.Self());
Calin Juravle7b0648a2017-07-07 18:40:50 -0700367 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
368 soa.Decode<mirror::ClassLoader>(jclass_loader));
369
Calin Juravlec79470d2017-07-12 17:37:42 -0700370 // An empty context should create a single PathClassLoader with only the compilation sources.
371 VerifyClassLoaderDexFiles(soa,
372 class_loader,
373 WellKnownClasses::dalvik_system_PathClassLoader,
374 compilation_sources_raw);
Calin Juravle7b0648a2017-07-07 18:40:50 -0700375 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
376 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
Calin Juravle7b0648a2017-07-07 18:40:50 -0700377}
378
Calin Juravle1a509c82017-07-24 16:51:21 -0700379TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
380 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
381
382 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
383
384 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
385
386 std::vector<const DexFile*> compilation_sources_raw =
387 MakeNonOwningPointerVector(compilation_sources);
388 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
389 ASSERT_TRUE(jclass_loader != nullptr);
390
391 ScopedObjectAccess soa(Thread::Current());
392
393 StackHandleScope<1> hs(soa.Self());
394 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
395 soa.Decode<mirror::ClassLoader>(jclass_loader));
396
397 // A shared library context should create a single PathClassLoader with only the compilation
398 // sources.
399 VerifyClassLoaderDexFiles(soa,
400 class_loader,
401 WellKnownClasses::dalvik_system_PathClassLoader,
402 compilation_sources_raw);
403 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
404 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
405}
406
Calin Juravlec79470d2017-07-12 17:37:42 -0700407TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
408 // Setup the context.
409 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
410 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
411 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
412 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
413
414 std::string context_spec =
415 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
416 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
417 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
418
419 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
420 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
421
422 // Setup the compilation sources.
423 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
424 std::vector<const DexFile*> compilation_sources_raw =
425 MakeNonOwningPointerVector(compilation_sources);
426
427 // Create the class loader.
428 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
429 ASSERT_TRUE(jclass_loader != nullptr);
430
431 // Verify the class loader.
432 ScopedObjectAccess soa(Thread::Current());
433
434 StackHandleScope<3> hs(soa.Self());
435 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
436 soa.Decode<mirror::ClassLoader>(jclass_loader));
437
438 // Verify the first class loader
439
440 // For the first class loader the class path dex files must come first and then the
441 // compilation sources.
442 std::vector<const DexFile*> class_loader_1_dex_files =
443 MakeNonOwningPointerVector(classpath_dex_a);
444 for (auto& dex : classpath_dex_b) {
445 class_loader_1_dex_files.push_back(dex.get());
446 }
447 for (auto& dex : compilation_sources_raw) {
448 class_loader_1_dex_files.push_back(dex);
449 }
450 VerifyClassLoaderDexFiles(soa,
451 class_loader_1,
452 WellKnownClasses::dalvik_system_PathClassLoader,
453 class_loader_1_dex_files);
454
455 // Verify the second class loader
456 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
457 std::vector<const DexFile*> class_loader_2_dex_files =
458 MakeNonOwningPointerVector(classpath_dex_c);
459 VerifyClassLoaderDexFiles(soa,
460 class_loader_2,
461 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
462 class_loader_2_dex_files);
463
464 // Verify the third class loader
465 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
466 std::vector<const DexFile*> class_loader_3_dex_files =
467 MakeNonOwningPointerVector(classpath_dex_d);
468 VerifyClassLoaderDexFiles(soa,
469 class_loader_3,
470 WellKnownClasses::dalvik_system_PathClassLoader,
471 class_loader_3_dex_files);
472 // The last class loader should have the BootClassLoader as a parent.
473 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
474 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
475}
476
477
Calin Juravle87e2cb62017-06-13 21:48:45 -0700478TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
479 std::unique_ptr<ClassLoaderContext> context =
480 ClassLoaderContext::Create("PCL[a.dex]");
481 dchecked_vector<std::string> classpath_dex;
482 classpath_dex.push_back("a.dex");
483 dchecked_vector<std::string> compilation_sources;
484 compilation_sources.push_back("src.dex");
485
486 // Nothing should be removed.
487 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
488 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
489 // Classes should be removed.
490 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
491 VerifyClassLoaderPCL(context.get(), 0, "");
492}
493
494TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
495 std::string dex1_name = GetTestDexFileName("Main");
496 std::string dex2_name = GetTestDexFileName("MyClass");
497 std::unique_ptr<ClassLoaderContext> context =
498 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
499 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
500
501 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
502 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
503 std::string encoding = context->EncodeContextForOatFile("");
Calin Juravlec79470d2017-07-12 17:37:42 -0700504 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
505 CreateClassPathWithChecksums(dex2) + "]";
Calin Juravle87e2cb62017-06-13 21:48:45 -0700506 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
507}
508
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700509TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
510 std::string dex1_name = GetTestDexFileName("Main");
511 std::string dex2_name = GetTestDexFileName("MultiDex");
512 std::unique_ptr<ClassLoaderContext> context =
513 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
514 ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
515
516 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
517 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MultiDex");
518 std::string encoding = context->EncodeContextForDex2oat("");
519 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
520 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
521}
522
Calin Juravle57d0acc2017-07-11 17:41:30 -0700523// TODO(calin) add a test which creates the context for a class loader together with dex_elements.
524TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
525 // The chain is
526 // ClassLoaderA (PathClassLoader)
527 // ^
528 // |
529 // ClassLoaderB (DelegateLastClassLoader)
530 // ^
531 // |
532 // ClassLoaderC (PathClassLoader)
533 // ^
534 // |
535 // ClassLoaderD (DelegateLastClassLoader)
536
537 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
538 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
539 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
540 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
541
542 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
543
544 VerifyContextForClassLoader(context.get());
545 VerifyContextSize(context.get(), 4);
546
547 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
548 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
549 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
550 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
551}
552
Calin Juravle3f918642017-07-11 19:04:20 -0700553TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
554 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
555 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
556
557 VerifyContextSize(context.get(), 2);
558 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
559 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
560
561 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
562
563 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
564 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
565
566 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
567 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
568
569 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
570 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
571
572 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
573 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
574
575 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
576 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
577
578 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
579 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
580
581 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
582 ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
583}
584
585TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
586 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
587 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
588 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
589 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
590
591 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
592
593 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
594}
595
Calin Juravlea308a322017-07-18 16:51:51 -0700596TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
597 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
598
599 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
600
601 ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
602}
603
Calin Juravle87e2cb62017-06-13 21:48:45 -0700604} // namespace art