1 /*
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 "class_loader_context.h"
18
19 #include <gtest/gtest.h>
20
21 #include "android-base/strings.h"
22 #include "art_field-inl.h"
23 #include "base/dchecked_vector.h"
24 #include "base/stl_util.h"
25 #include "class_linker.h"
26 #include "class_root-inl.h"
27 #include "common_runtime_test.h"
28 #include "dex/dex_file.h"
29 #include "handle_scope-inl.h"
30 #include "jni/jni_internal.h"
31 #include "mirror/class.h"
32 #include "mirror/class_loader-inl.h"
33 #include "mirror/object-inl.h"
34 #include "mirror/object_array-alloc-inl.h"
35 #include "oat_file_assistant.h"
36 #include "runtime.h"
37 #include "scoped_thread_state_change-inl.h"
38 #include "thread.h"
39 #include "well_known_classes.h"
40
41 namespace art {
42
43 class ClassLoaderContextTest : public CommonRuntimeTest {
44 public:
VerifyContextSize(ClassLoaderContext * context,size_t expected_size)45 void VerifyContextSize(ClassLoaderContext* context, size_t expected_size) {
46 ASSERT_TRUE(context != nullptr);
47 ASSERT_EQ(expected_size, context->GetParentChainSize());
48 }
49
VerifyClassLoaderPCL(ClassLoaderContext * context,size_t index,const std::string & classpath)50 void VerifyClassLoaderPCL(ClassLoaderContext* context,
51 size_t index,
52 const std::string& classpath) {
53 VerifyClassLoaderInfo(
54 context, index, ClassLoaderContext::kPathClassLoader, classpath);
55 }
56
VerifyClassLoaderDLC(ClassLoaderContext * context,size_t index,const std::string & classpath)57 void VerifyClassLoaderDLC(ClassLoaderContext* context,
58 size_t index,
59 const std::string& classpath) {
60 VerifyClassLoaderInfo(
61 context, index, ClassLoaderContext::kDelegateLastClassLoader, classpath);
62 }
63
VerifyClassLoaderIMC(ClassLoaderContext * context,size_t index,const std::string & classpath)64 void VerifyClassLoaderIMC(ClassLoaderContext* context,
65 size_t index,
66 const std::string& classpath) {
67 VerifyClassLoaderInfo(
68 context, index, ClassLoaderContext::kInMemoryDexClassLoader, classpath);
69 }
70
VerifyClassLoaderSharedLibraryPCL(ClassLoaderContext * context,size_t loader_index,size_t shared_library_index,const std::string & classpath)71 void VerifyClassLoaderSharedLibraryPCL(ClassLoaderContext* context,
72 size_t loader_index,
73 size_t shared_library_index,
74 const std::string& classpath) {
75 VerifyClassLoaderInfoSL(
76 context, loader_index, shared_library_index, ClassLoaderContext::kPathClassLoader,
77 classpath);
78 }
79
VerifyClassLoaderSharedLibraryIMC(ClassLoaderContext * context,size_t loader_index,size_t shared_library_index,const std::string & classpath)80 void VerifyClassLoaderSharedLibraryIMC(ClassLoaderContext* context,
81 size_t loader_index,
82 size_t shared_library_index,
83 const std::string& classpath) {
84 VerifyClassLoaderInfoSL(
85 context, loader_index, shared_library_index, ClassLoaderContext::kInMemoryDexClassLoader,
86 classpath);
87 }
88
VerifySharedLibrariesSize(ClassLoaderContext * context,size_t loader_index,size_t expected_size)89 void VerifySharedLibrariesSize(ClassLoaderContext* context,
90 size_t loader_index,
91 size_t expected_size) {
92 ASSERT_TRUE(context != nullptr);
93 ASSERT_GT(context->GetParentChainSize(), loader_index);
94 const ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(loader_index);
95 ASSERT_EQ(info.shared_libraries.size(), expected_size);
96 }
97
VerifyClassLoaderSharedLibraryDLC(ClassLoaderContext * context,size_t loader_index,size_t shared_library_index,const std::string & classpath)98 void VerifyClassLoaderSharedLibraryDLC(ClassLoaderContext* context,
99 size_t loader_index,
100 size_t shared_library_index,
101 const std::string& classpath) {
102 VerifyClassLoaderInfoSL(
103 context, loader_index, shared_library_index, ClassLoaderContext::kDelegateLastClassLoader,
104 classpath);
105 }
106
VerifyClassLoaderPCLFromTestDex(ClassLoaderContext * context,size_t index,const std::string & test_name)107 void VerifyClassLoaderPCLFromTestDex(ClassLoaderContext* context,
108 size_t index,
109 const std::string& test_name) {
110 VerifyClassLoaderFromTestDex(
111 context, index, ClassLoaderContext::kPathClassLoader, test_name);
112 }
113
VerifyClassLoaderDLCFromTestDex(ClassLoaderContext * context,size_t index,const std::string & test_name)114 void VerifyClassLoaderDLCFromTestDex(ClassLoaderContext* context,
115 size_t index,
116 const std::string& test_name) {
117 VerifyClassLoaderFromTestDex(
118 context, index, ClassLoaderContext::kDelegateLastClassLoader, test_name);
119 }
120
VerifyClassLoaderIMCFromTestDex(ClassLoaderContext * context,size_t index,const std::string & test_name)121 void VerifyClassLoaderIMCFromTestDex(ClassLoaderContext* context,
122 size_t index,
123 const std::string& test_name) {
124 VerifyClassLoaderFromTestDex(
125 context, index, ClassLoaderContext::kInMemoryDexClassLoader, test_name, "<unknown>");
126 }
127
128 enum class LocationCheck {
129 kEquals,
130 kEndsWith
131 };
132 enum class BaseLocationCheck {
133 kEquals,
134 kEndsWith
135 };
136
IsAbsoluteLocation(const std::string & location)137 static bool IsAbsoluteLocation(const std::string& location) {
138 return !location.empty() && location[0] == '/';
139 }
140
VerifyOpenDexFiles(ClassLoaderContext * context,size_t index,std::vector<std::unique_ptr<const DexFile>> * all_dex_files,bool classpath_matches_dex_location=true,bool only_read_checksums=false)141 void VerifyOpenDexFiles(
142 ClassLoaderContext* context,
143 size_t index,
144 std::vector<std::unique_ptr<const DexFile>>* all_dex_files,
145 bool classpath_matches_dex_location = true,
146 bool only_read_checksums = false) {
147 ASSERT_TRUE(context != nullptr);
148 if (only_read_checksums) {
149 ASSERT_EQ(context->dex_files_state_,
150 ClassLoaderContext::ContextDexFilesState::kDexFilesChecksumsRead);
151 } else {
152 ASSERT_EQ(context->dex_files_state_,
153 ClassLoaderContext::ContextDexFilesState::kDexFilesOpened);
154 }
155 ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(index);
156 ASSERT_EQ(all_dex_files->size(), info.classpath.size());
157 ASSERT_EQ(all_dex_files->size(), info.checksums.size());
158 if (only_read_checksums) {
159 ASSERT_EQ(0u, info.opened_dex_files.size());
160 } else {
161 ASSERT_EQ(all_dex_files->size(), info.opened_dex_files.size());
162 }
163
164 for (size_t k = 0, cur_open_dex_index = 0;
165 k < all_dex_files->size();
166 k++, cur_open_dex_index++) {
167 const std::string& opened_location = only_read_checksums
168 ? info.classpath[cur_open_dex_index]
169 : info.opened_dex_files[cur_open_dex_index]->GetLocation();
170 uint32_t opened_checksum = only_read_checksums
171 ? info.checksums[cur_open_dex_index]
172 : info.opened_dex_files[cur_open_dex_index]->GetLocationChecksum();
173
174 std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k];
175 std::string expected_location = expected_dex_file->GetLocation();
176
177 if (!IsAbsoluteLocation(opened_location)) {
178 // If the opened location is relative (it was open from a relative path without a
179 // classpath_dir) it might not match the expected location which is absolute in tests).
180 // So we compare the endings (the checksum will validate it's actually the same file).
181 ASSERT_EQ(0, expected_location.compare(
182 expected_location.length() - opened_location.length(),
183 opened_location.length(),
184 opened_location));
185 } else {
186 ASSERT_EQ(expected_location, opened_location);
187 }
188 ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_checksum);
189 if (classpath_matches_dex_location) {
190 ASSERT_EQ(info.classpath[k], opened_location);
191 }
192 }
193 }
194
CreateContextForClassLoader(jobject class_loader)195 std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
196 return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
197 }
198
ParseContextWithChecksums(const std::string & context_spec)199 std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
200 std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
201 if (!context->Parse(context_spec, /*parse_checksums=*/ true)) {
202 return nullptr;
203 }
204 return context;
205 }
206
VerifyContextForClassLoader(ClassLoaderContext * context)207 void VerifyContextForClassLoader(ClassLoaderContext* context) {
208 ASSERT_TRUE(context != nullptr);
209 ASSERT_EQ(context->dex_files_state_, ClassLoaderContext::ContextDexFilesState::kDexFilesOpened);
210 ASSERT_FALSE(context->owns_the_dex_files_);
211 }
212
VerifyClassLoaderDexFiles(ScopedObjectAccess & soa,Handle<mirror::ClassLoader> class_loader,jclass type,std::vector<const DexFile * > & expected_dex_files)213 void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
214 Handle<mirror::ClassLoader> class_loader,
215 jclass type,
216 std::vector<const DexFile*>& expected_dex_files)
217 REQUIRES_SHARED(Locks::mutator_lock_) {
218 ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
219
220 std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
221 ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
222
223 for (size_t i = 0; i < expected_dex_files.size(); i++) {
224 ASSERT_EQ(expected_dex_files[i]->GetLocation(),
225 class_loader_dex_files[i]->GetLocation());
226 ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
227 class_loader_dex_files[i]->GetLocationChecksum());
228 }
229 }
230
PretendContextOpenedDexFiles(ClassLoaderContext * context)231 void PretendContextOpenedDexFiles(ClassLoaderContext* context) {
232 context->dex_files_state_ = ClassLoaderContext::ContextDexFilesState::kDexFilesOpened;
233 }
234
PretendContextOpenedDexFilesForChecksums(ClassLoaderContext * context)235 void PretendContextOpenedDexFilesForChecksums(ClassLoaderContext* context) {
236 context->dex_files_state_ = ClassLoaderContext::ContextDexFilesState::kDexFilesChecksumsRead;
237 }
238
TestOpenDexFiles(bool only_read_checksums)239 void TestOpenDexFiles(bool only_read_checksums) {
240 std::string multidex_name = GetTestDexFileName("MultiDex");
241 std::string myclass_dex_name = GetTestDexFileName("MyClass");
242 std::string dex_name = GetTestDexFileName("Main");
243
244 std::unique_ptr<ClassLoaderContext> context =
245 ClassLoaderContext::Create(
246 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
247 "DLC[" + dex_name + "]");
248
249 ASSERT_TRUE(context->OpenDexFiles(
250 /*classpath_dir=*/ "",
251 /*context_fds=*/ std::vector<int>(),
252 only_read_checksums));
253
254 VerifyContextSize(context.get(), 2);
255
256 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
257 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
258 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
259 all_dex_files0.emplace_back(myclass_dex_files[i].release());
260 }
261 VerifyOpenDexFiles(context.get(),
262 /*index=*/ 0,
263 &all_dex_files0,
264 /*classpath_matches_dex_location=*/ false,
265 only_read_checksums);
266 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
267 VerifyOpenDexFiles(context.get(),
268 /*index=*/ 1,
269 &all_dex_files1,
270 /*classpath_matches_dex_location=*/ false,
271 only_read_checksums);
272 }
273
TestOpenValidDexFilesRelative(bool use_classpath_dir,bool only_read_checksums)274 void TestOpenValidDexFilesRelative(bool use_classpath_dir, bool only_read_checksums) {
275 char cwd_buf[4096];
276 if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
277 PLOG(FATAL) << "Could not get working directory";
278 }
279 std::string multidex_name;
280 std::string myclass_dex_name;
281 std::string dex_name;
282 if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
283 !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
284 !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
285 LOG(ERROR) << "Test OpenValidDexFilesRelative cannot be run because target dex files have no "
286 << "relative path.";
287 SUCCEED();
288 return;
289 }
290
291 std::unique_ptr<ClassLoaderContext> context =
292 ClassLoaderContext::Create(
293 "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
294 "DLC[" + dex_name + "]");
295
296 ASSERT_TRUE(context->OpenDexFiles(
297 /*classpath_dir=*/ use_classpath_dir ? cwd_buf : "",
298 /*context_fds=*/ std::vector<int>(),
299 only_read_checksums));
300 VerifyContextSize(context.get(), 2);
301
302 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
303 std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
304 for (size_t i = 0; i < myclass_dex_files.size(); i++) {
305 all_dex_files0.emplace_back(myclass_dex_files[i].release());
306 }
307 VerifyOpenDexFiles(context.get(),
308 /*index=*/ 0,
309 &all_dex_files0,
310 /*classpath_matches_dex_location=*/ false,
311 only_read_checksums);
312
313 std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
314 VerifyOpenDexFiles(context.get(),
315 /*index=*/ 1,
316 &all_dex_files1,
317 /*classpath_matches_dex_location=*/ false,
318 only_read_checksums);
319 }
320
321 // Creates a relative path from cwd to 'in'. Returns false if it cannot be done.
322 // TODO We should somehow support this in all situations. b/72042237.
CreateRelativeString(const std::string & in,const char * cwd,std::string * out)323 bool CreateRelativeString(const std::string& in, const char* cwd, std::string* out) {
324 int cwd_len = strlen(cwd);
325 if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
326 return false;
327 }
328 bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
329 int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
330 *out = in.substr(start_position);
331 return true;
332 }
333
334 private:
VerifyClassLoaderInfo(ClassLoaderContext * context,size_t index,ClassLoaderContext::ClassLoaderType type,const std::string & classpath)335 void VerifyClassLoaderInfo(ClassLoaderContext* context,
336 size_t index,
337 ClassLoaderContext::ClassLoaderType type,
338 const std::string& classpath) {
339 ASSERT_TRUE(context != nullptr);
340 ASSERT_GT(context->GetParentChainSize(), index);
341 ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(index);
342 ASSERT_EQ(type, info.type);
343 std::vector<std::string> expected_classpath;
344 Split(classpath, ':', &expected_classpath);
345 ASSERT_EQ(expected_classpath, info.classpath);
346 }
347
VerifyClassLoaderInfoSL(ClassLoaderContext * context,size_t loader_index,size_t shared_library_index,ClassLoaderContext::ClassLoaderType type,const std::string & classpath)348 void VerifyClassLoaderInfoSL(ClassLoaderContext* context,
349 size_t loader_index,
350 size_t shared_library_index,
351 ClassLoaderContext::ClassLoaderType type,
352 const std::string& classpath) {
353 ASSERT_TRUE(context != nullptr);
354 ASSERT_GT(context->GetParentChainSize(), loader_index);
355 const ClassLoaderContext::ClassLoaderInfo& info = *context->GetParent(loader_index);
356 ASSERT_GT(info.shared_libraries.size(), shared_library_index);
357 const ClassLoaderContext::ClassLoaderInfo& sl =
358 *info.shared_libraries[shared_library_index].get();
359 ASSERT_EQ(type, info.type);
360 std::vector<std::string> expected_classpath;
361 Split(classpath, ':', &expected_classpath);
362 ASSERT_EQ(expected_classpath, sl.classpath);
363 }
364
VerifyClassLoaderFromTestDex(ClassLoaderContext * context,size_t index,ClassLoaderContext::ClassLoaderType type,const std::string & test_name,const std::string & classpath="")365 void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
366 size_t index,
367 ClassLoaderContext::ClassLoaderType type,
368 const std::string& test_name,
369 const std::string& classpath = "") {
370 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
371
372 // If `classpath` is set, override the expected value of ClassLoaderInfo::classpath.
373 // Otherwise assume it is equal to dex location (here test dex file name).
374 VerifyClassLoaderInfo(context,
375 index,
376 type,
377 classpath.empty() ? GetTestDexFileName(test_name.c_str()) : classpath);
378 VerifyOpenDexFiles(context,
379 index,
380 &dex_files,
381 /* classpath_matches_dex_location= */ classpath.empty());
382 }
383 };
384
TEST_F(ClassLoaderContextTest,ParseValidEmptyContext)385 TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
386 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
387 // An empty context should create a single empty PathClassLoader.
388 VerifyContextSize(context.get(), 1);
389 VerifyClassLoaderPCL(context.get(), 0, "");
390 }
391
TEST_F(ClassLoaderContextTest,ParseInvalidSharedLibraryContext)392 TEST_F(ClassLoaderContextTest, ParseInvalidSharedLibraryContext) {
393 // '&' used to be a special context.
394 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
395 ASSERT_TRUE(context == nullptr);
396 }
397
TEST_F(ClassLoaderContextTest,ParseValidContextPCL)398 TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
399 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("PCL[a.dex]");
400 VerifyContextSize(context.get(), 1);
401 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
402 }
403
TEST_F(ClassLoaderContextTest,ParseValidContextDLC)404 TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
405 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("DLC[a.dex]");
406 VerifyContextSize(context.get(), 1);
407 VerifyClassLoaderDLC(context.get(), 0, "a.dex");
408 }
409
TEST_F(ClassLoaderContextTest,ParseValidContextIMC)410 TEST_F(ClassLoaderContextTest, ParseValidContextIMC) {
411 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums("IMC[<unknown>*111]");
412 ASSERT_FALSE(context == nullptr);
413 }
414
TEST_F(ClassLoaderContextTest,ParseInvalidContextIMCNoChecksum)415 TEST_F(ClassLoaderContextTest, ParseInvalidContextIMCNoChecksum) {
416 // IMC is treated as an unknown class loader unless a checksum is provided.
417 // This is because the dex location is always bogus.
418 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("IMC[<unknown>]");
419 ASSERT_TRUE(context == nullptr);
420 }
421
TEST_F(ClassLoaderContextTest,ParseInvalidContextIMCWrongClasspathMagic)422 TEST_F(ClassLoaderContextTest, ParseInvalidContextIMCWrongClasspathMagic) {
423 // IMC does not support arbitrary dex location. A magic marker must be used
424 // otherwise the spec should be rejected.
425 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("IMC[a.dex*111]");
426 ASSERT_TRUE(context == nullptr);
427 }
428
TEST_F(ClassLoaderContextTest,ParseValidContextChain)429 TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
430 std::unique_ptr<ClassLoaderContext> context =
431 ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
432 VerifyContextSize(context.get(), 3);
433 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
434 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
435 VerifyClassLoaderPCL(context.get(), 2, "e.dex");
436 }
437
TEST_F(ClassLoaderContextTest,ParseSharedLibraries)438 TEST_F(ClassLoaderContextTest, ParseSharedLibraries) {
439 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
440 "PCL[a.dex:b.dex]{PCL[s1.dex]#PCL[s2.dex:s3.dex]};DLC[c.dex:d.dex]{DLC[s4.dex]}");
441 VerifyContextSize(context.get(), 2);
442 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s1.dex");
443 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 1, "s2.dex:s3.dex");
444 VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
445 VerifyClassLoaderSharedLibraryDLC(context.get(), 1, 0, "s4.dex");
446 }
447
TEST_F(ClassLoaderContextTest,ParseEnclosingSharedLibraries)448 TEST_F(ClassLoaderContextTest, ParseEnclosingSharedLibraries) {
449 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
450 "PCL[a.dex:b.dex]{PCL[s1.dex]{PCL[s2.dex:s3.dex];PCL[s4.dex]}}");
451 VerifyContextSize(context.get(), 1);
452 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s1.dex");
453 }
454
TEST_F(ClassLoaderContextTest,ParseComplexSharedLibraries1)455 TEST_F(ClassLoaderContextTest, ParseComplexSharedLibraries1) {
456 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
457 "PCL[]{PCL[s4.dex]{PCL[s5.dex]{PCL[s6.dex]}#PCL[s6.dex]}}");
458 VerifyContextSize(context.get(), 1);
459 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s4.dex");
460 }
461
TEST_F(ClassLoaderContextTest,ParseComplexSharedLibraries2)462 TEST_F(ClassLoaderContextTest, ParseComplexSharedLibraries2) {
463 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(
464 "PCL[]{PCL[s1.dex]{PCL[s2.dex]}#PCL[s2.dex]#"
465 "PCL[s3.dex]#PCL[s4.dex]{PCL[s5.dex]{PCL[s6.dex]}#PCL[s6.dex]}#PCL[s5.dex]{PCL[s6.dex]}}");
466 VerifyContextSize(context.get(), 1);
467 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "s1.dex");
468 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 1, "s2.dex");
469 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 2, "s3.dex");
470 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 3, "s4.dex");
471 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 4, "s5.dex");
472 }
473
TEST_F(ClassLoaderContextTest,ParseValidEmptyContextDLC)474 TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
475 std::unique_ptr<ClassLoaderContext> context =
476 ClassLoaderContext::Create("DLC[]");
477 VerifyContextSize(context.get(), 1);
478 VerifyClassLoaderDLC(context.get(), 0, "");
479 }
480
TEST_F(ClassLoaderContextTest,ParseValidEmptyContextSharedLibrary)481 TEST_F(ClassLoaderContextTest, ParseValidEmptyContextSharedLibrary) {
482 std::unique_ptr<ClassLoaderContext> context =
483 ClassLoaderContext::Create("DLC[]{}");
484 VerifyContextSize(context.get(), 1);
485 VerifySharedLibrariesSize(context.get(), 0, 0);
486 }
487
TEST_F(ClassLoaderContextTest,ParseInvalidValidContexts)488 TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
489 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
490 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
491 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
492 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
493 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
494 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
495 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex]{ABC};DLC[b.dex"));
496 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex]{};DLC[b.dex"));
497 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("DLC[s4.dex]}"));
498 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("DLC[s4.dex]{"));
499 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("DLC{DLC[s4.dex]}"));
500 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{##}"));
501 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{PCL[s4.dex]#}"));
502 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{PCL[s4.dex]##}"));
503 ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{PCL[s4.dex]{PCL[s3.dex]}#}"));
504 }
505
TEST_F(ClassLoaderContextTest,OpenInvalidDexFiles)506 TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
507 std::unique_ptr<ClassLoaderContext> context =
508 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
509 VerifyContextSize(context.get(), 1);
510 ASSERT_FALSE(context->OpenDexFiles("."));
511 }
512
TEST_F(ClassLoaderContextTest,ReadChecksumsInvalidDexFiles)513 TEST_F(ClassLoaderContextTest, ReadChecksumsInvalidDexFiles) {
514 std::unique_ptr<ClassLoaderContext> context =
515 ClassLoaderContext::Create("PCL[does_not_exist.dex]");
516 VerifyContextSize(context.get(), 1);
517 ASSERT_FALSE(context->OpenDexFiles(
518 /*classpath_dir=*/ ".",
519 /*context_fds=*/ std::vector<int>(),
520 /*only_read_checksums=*/ true));
521 }
522
TEST_F(ClassLoaderContextTest,OpenValidDexFiles)523 TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
524 TestOpenDexFiles(/*only_read_checksums=*/ false);
525 }
526
TEST_F(ClassLoaderContextTest,ReadDexFileChecksums)527 TEST_F(ClassLoaderContextTest, ReadDexFileChecksums) {
528 TestOpenDexFiles(/*only_read_checksums=*/ true);
529 }
530
TEST_F(ClassLoaderContextTest,OpenValidDexFilesRelative)531 TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) {
532 TestOpenValidDexFilesRelative(/*use_classpath_dir=*/ false, /*only_read_checksums=*/ false);
533 }
534
TEST_F(ClassLoaderContextTest,ReadChecksumsValidDexFilesRelative)535 TEST_F(ClassLoaderContextTest, ReadChecksumsValidDexFilesRelative) {
536 TestOpenValidDexFilesRelative(/*use_classpath_dir=*/ false, /*only_read_checksums=*/ true);
537 }
538
TEST_F(ClassLoaderContextTest,OpenValidDexFilesClasspathDir)539 TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) {
540 TestOpenValidDexFilesRelative(/*use_classpath_dir=*/ true, /*only_read_checksums=*/ false);
541 }
542
TEST_F(ClassLoaderContextTest,ReadChecksumsValidDexFilesClasspathDir)543 TEST_F(ClassLoaderContextTest, ReadChecksumsValidDexFilesClasspathDir) {
544 TestOpenValidDexFilesRelative(/*use_classpath_dir=*/ true, /*only_read_checksums=*/ true);
545 }
546
TEST_F(ClassLoaderContextTest,OpenInvalidDexFilesMix)547 TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
548 std::string dex_name = GetTestDexFileName("Main");
549 std::unique_ptr<ClassLoaderContext> context =
550 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
551 ASSERT_FALSE(context->OpenDexFiles());
552 }
553
TEST_F(ClassLoaderContextTest,ReadChecksumsInvalidDexFilesMix)554 TEST_F(ClassLoaderContextTest, ReadChecksumsInvalidDexFilesMix) {
555 std::string dex_name = GetTestDexFileName("Main");
556 std::unique_ptr<ClassLoaderContext> context =
557 ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
558 ASSERT_FALSE(context->OpenDexFiles(
559 /*classpath_dir=*/ "",
560 /*context_fds=*/ std::vector<int>(),
561 /*only_read_checksums=*/ true));
562 }
563
TEST_F(ClassLoaderContextTest,OpenDexFilesForIMCFails)564 TEST_F(ClassLoaderContextTest, OpenDexFilesForIMCFails) {
565 std::unique_ptr<ClassLoaderContext> context;
566 std::string dex_name = GetTestDexFileName("Main");
567
568 context = ParseContextWithChecksums("IMC[<unknown>*111]");
569 VerifyContextSize(context.get(), 1);
570 ASSERT_FALSE(context->OpenDexFiles("."));
571 }
572
573 // Verify that we can fully open the dex files after only reading their checksums.
TEST_F(ClassLoaderContextTest,SubsequentOpenDexFilesOperations)574 TEST_F(ClassLoaderContextTest, SubsequentOpenDexFilesOperations) {
575 std::string dex_name = GetTestDexFileName("Main");
576 std::unique_ptr<ClassLoaderContext> context =
577 ClassLoaderContext::Create("PCL[" + dex_name + "]");
578
579 std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("Main");
580
581 ASSERT_TRUE(context->OpenDexFiles(
582 /*classpath_dir=*/ "",
583 /*context_fds=*/ std::vector<int>(),
584 /*only_read_checksums=*/ true));
585
586 VerifyOpenDexFiles(
587 context.get(),
588 /*index=*/ 0,
589 &all_dex_files0,
590 /*classpath_matches_dex_location=*/ false,
591 /*only_read_checksums=*/ true);
592
593 ASSERT_TRUE(context->OpenDexFiles(
594 /*classpath_dir=*/ "",
595 /*context_fds=*/ std::vector<int>(),
596 /*only_read_checksums=*/ false));
597
598 VerifyOpenDexFiles(
599 context.get(),
600 /*index=*/ 0,
601 &all_dex_files0,
602 /*classpath_matches_dex_location=*/ false,
603 /*only_read_checksums=*/ false);
604 }
605
TEST_F(ClassLoaderContextTest,CreateClassLoader)606 TEST_F(ClassLoaderContextTest, CreateClassLoader) {
607 std::string dex_name = GetTestDexFileName("Main");
608 std::unique_ptr<ClassLoaderContext> context =
609 ClassLoaderContext::Create("PCL[" + dex_name + "]");
610 ASSERT_TRUE(context->OpenDexFiles());
611
612 std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
613 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
614
615 std::vector<const DexFile*> compilation_sources_raw =
616 MakeNonOwningPointerVector(compilation_sources);
617 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
618 ASSERT_TRUE(jclass_loader != nullptr);
619
620 ScopedObjectAccess soa(Thread::Current());
621
622 StackHandleScope<1> hs(soa.Self());
623 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
624 soa.Decode<mirror::ClassLoader>(jclass_loader));
625
626 ASSERT_TRUE(class_loader->GetClass() ==
627 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
628 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
629 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
630
631 // For the first class loader the class path dex files must come first and then the
632 // compilation sources.
633 std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
634 for (auto& dex : compilation_sources_raw) {
635 expected_classpath.push_back(dex);
636 }
637
638 VerifyClassLoaderDexFiles(soa,
639 class_loader,
640 WellKnownClasses::dalvik_system_PathClassLoader,
641 expected_classpath);
642 }
643
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithEmptyContext)644 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
645 std::unique_ptr<ClassLoaderContext> context =
646 ClassLoaderContext::Create("");
647 ASSERT_TRUE(context->OpenDexFiles());
648
649 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
650
651 std::vector<const DexFile*> compilation_sources_raw =
652 MakeNonOwningPointerVector(compilation_sources);
653 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
654 ASSERT_TRUE(jclass_loader != nullptr);
655
656 ScopedObjectAccess soa(Thread::Current());
657
658 StackHandleScope<1> hs(soa.Self());
659 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
660 soa.Decode<mirror::ClassLoader>(jclass_loader));
661
662 // An empty context should create a single PathClassLoader with only the compilation sources.
663 VerifyClassLoaderDexFiles(soa,
664 class_loader,
665 WellKnownClasses::dalvik_system_PathClassLoader,
666 compilation_sources_raw);
667 ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
668 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
669 }
670
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithComplexChain)671 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
672 // Setup the context.
673 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
674 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
675 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
676 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
677
678 std::string context_spec =
679 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
680 "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
681 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
682
683 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
684 ASSERT_TRUE(context->OpenDexFiles());
685
686 // Setup the compilation sources.
687 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
688 std::vector<const DexFile*> compilation_sources_raw =
689 MakeNonOwningPointerVector(compilation_sources);
690
691 // Create the class loader.
692 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
693 ASSERT_TRUE(jclass_loader != nullptr);
694
695 // Verify the class loader.
696 ScopedObjectAccess soa(Thread::Current());
697
698 StackHandleScope<3> hs(soa.Self());
699 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
700 soa.Decode<mirror::ClassLoader>(jclass_loader));
701
702 // Verify the first class loader
703
704 // For the first class loader the class path dex files must come first and then the
705 // compilation sources.
706 std::vector<const DexFile*> class_loader_1_dex_files =
707 MakeNonOwningPointerVector(classpath_dex_a);
708 for (auto& dex : classpath_dex_b) {
709 class_loader_1_dex_files.push_back(dex.get());
710 }
711 for (auto& dex : compilation_sources_raw) {
712 class_loader_1_dex_files.push_back(dex);
713 }
714 VerifyClassLoaderDexFiles(soa,
715 class_loader_1,
716 WellKnownClasses::dalvik_system_PathClassLoader,
717 class_loader_1_dex_files);
718
719 // Verify the second class loader
720 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
721 std::vector<const DexFile*> class_loader_2_dex_files =
722 MakeNonOwningPointerVector(classpath_dex_c);
723 VerifyClassLoaderDexFiles(soa,
724 class_loader_2,
725 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
726 class_loader_2_dex_files);
727
728 // Verify the third class loader
729 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
730 std::vector<const DexFile*> class_loader_3_dex_files =
731 MakeNonOwningPointerVector(classpath_dex_d);
732 VerifyClassLoaderDexFiles(soa,
733 class_loader_3,
734 WellKnownClasses::dalvik_system_PathClassLoader,
735 class_loader_3_dex_files);
736 // The last class loader should have the BootClassLoader as a parent.
737 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
738 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
739 }
740
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSharedLibraries)741 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraries) {
742 // Setup the context.
743 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
744 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
745 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
746 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
747
748 std::string context_spec =
749 "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "]{" +
750 "DLC[" + CreateClassPath(classpath_dex_c) + "]#" +
751 "PCL[" + CreateClassPath(classpath_dex_d) + "]}";
752
753 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
754 ASSERT_TRUE(context->OpenDexFiles());
755
756 // Setup the compilation sources.
757 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
758 std::vector<const DexFile*> compilation_sources_raw =
759 MakeNonOwningPointerVector(compilation_sources);
760
761 // Create the class loader.
762 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
763 ASSERT_TRUE(jclass_loader != nullptr);
764
765 // Verify the class loader.
766 ScopedObjectAccess soa(Thread::Current());
767
768 StackHandleScope<4> hs(soa.Self());
769 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
770 soa.Decode<mirror::ClassLoader>(jclass_loader));
771
772 // For the first class loader the class path dex files must come first and then the
773 // compilation sources.
774 std::vector<const DexFile*> class_loader_1_dex_files =
775 MakeNonOwningPointerVector(classpath_dex_a);
776 for (auto& dex : classpath_dex_b) {
777 class_loader_1_dex_files.push_back(dex.get());
778 }
779 for (auto& dex : compilation_sources_raw) {
780 class_loader_1_dex_files.push_back(dex);
781 }
782 VerifyClassLoaderDexFiles(soa,
783 class_loader_1,
784 WellKnownClasses::dalvik_system_PathClassLoader,
785 class_loader_1_dex_files);
786
787 // Verify the shared libraries.
788 ArtField* field =
789 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
790 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader_1.Get());
791 ASSERT_TRUE(raw_shared_libraries != nullptr);
792
793 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries(
794 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
795 ASSERT_EQ(shared_libraries->GetLength(), 2);
796
797 // Verify the first shared library.
798 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(shared_libraries->Get(0));
799 std::vector<const DexFile*> class_loader_2_dex_files =
800 MakeNonOwningPointerVector(classpath_dex_c);
801 VerifyClassLoaderDexFiles(soa,
802 class_loader_2,
803 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
804 class_loader_2_dex_files);
805 raw_shared_libraries = field->GetObject(class_loader_2.Get());
806 ASSERT_TRUE(raw_shared_libraries == nullptr);
807
808 // Verify the second shared library.
809 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(shared_libraries->Get(1));
810 std::vector<const DexFile*> class_loader_3_dex_files =
811 MakeNonOwningPointerVector(classpath_dex_d);
812 VerifyClassLoaderDexFiles(soa,
813 class_loader_3,
814 WellKnownClasses::dalvik_system_PathClassLoader,
815 class_loader_3_dex_files);
816 raw_shared_libraries = field->GetObject(class_loader_3.Get());
817 ASSERT_TRUE(raw_shared_libraries == nullptr);
818
819 // All class loaders should have the BootClassLoader as a parent.
820 ASSERT_TRUE(class_loader_1->GetParent()->GetClass() ==
821 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
822 ASSERT_TRUE(class_loader_2->GetParent()->GetClass() ==
823 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
824 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
825 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
826 }
827
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSharedLibrariesInParentToo)828 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibrariesInParentToo) {
829 // Setup the context.
830 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
831 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
832 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
833 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
834
835 std::string context_spec =
836 "PCL[" + CreateClassPath(classpath_dex_a) + "]{" +
837 "PCL[" + CreateClassPath(classpath_dex_b) + "]};" +
838 "PCL[" + CreateClassPath(classpath_dex_c) + "]{" +
839 "PCL[" + CreateClassPath(classpath_dex_d) + "]}";
840
841 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
842 ASSERT_TRUE(context->OpenDexFiles());
843
844 // Setup the compilation sources.
845 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
846 std::vector<const DexFile*> compilation_sources_raw =
847 MakeNonOwningPointerVector(compilation_sources);
848
849 // Create the class loader.
850 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
851 ASSERT_TRUE(jclass_loader != nullptr);
852
853 // Verify the class loader.
854 ScopedObjectAccess soa(Thread::Current());
855
856 StackHandleScope<6> hs(soa.Self());
857 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
858 soa.Decode<mirror::ClassLoader>(jclass_loader));
859
860 // For the first class loader the class path dex files must come first and then the
861 // compilation sources.
862 std::vector<const DexFile*> class_loader_1_dex_files =
863 MakeNonOwningPointerVector(classpath_dex_a);
864 for (auto& dex : compilation_sources_raw) {
865 class_loader_1_dex_files.push_back(dex);
866 }
867 VerifyClassLoaderDexFiles(soa,
868 class_loader_1,
869 WellKnownClasses::dalvik_system_PathClassLoader,
870 class_loader_1_dex_files);
871
872 // Verify its shared library.
873 ArtField* field =
874 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
875 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader_1.Get());
876 ASSERT_TRUE(raw_shared_libraries != nullptr);
877
878 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries(
879 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
880 ASSERT_EQ(shared_libraries->GetLength(), 1);
881
882 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(shared_libraries->Get(0));
883 std::vector<const DexFile*> class_loader_2_dex_files =
884 MakeNonOwningPointerVector(classpath_dex_b);
885 VerifyClassLoaderDexFiles(soa,
886 class_loader_2,
887 WellKnownClasses::dalvik_system_PathClassLoader,
888 class_loader_2_dex_files);
889 raw_shared_libraries = field->GetObject(class_loader_2.Get());
890 ASSERT_TRUE(raw_shared_libraries == nullptr);
891
892 // Verify the parent.
893 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_1->GetParent());
894 std::vector<const DexFile*> class_loader_3_dex_files =
895 MakeNonOwningPointerVector(classpath_dex_c);
896 VerifyClassLoaderDexFiles(soa,
897 class_loader_3,
898 WellKnownClasses::dalvik_system_PathClassLoader,
899 class_loader_3_dex_files);
900
901 // Verify its shared library.
902 raw_shared_libraries = field->GetObject(class_loader_3.Get());
903 ASSERT_TRUE(raw_shared_libraries != nullptr);
904
905 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_2(
906 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
907 ASSERT_EQ(shared_libraries->GetLength(), 1);
908
909 Handle<mirror::ClassLoader> class_loader_4 = hs.NewHandle(shared_libraries_2->Get(0));
910 std::vector<const DexFile*> class_loader_4_dex_files =
911 MakeNonOwningPointerVector(classpath_dex_d);
912 VerifyClassLoaderDexFiles(soa,
913 class_loader_4,
914 WellKnownClasses::dalvik_system_PathClassLoader,
915 class_loader_4_dex_files);
916 raw_shared_libraries = field->GetObject(class_loader_4.Get());
917 ASSERT_TRUE(raw_shared_libraries == nullptr);
918
919 // Class loaders should have the BootClassLoader as a parent.
920 ASSERT_TRUE(class_loader_2->GetParent()->GetClass() ==
921 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
922 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
923 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
924 ASSERT_TRUE(class_loader_4->GetParent()->GetClass() ==
925 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
926 }
927
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSharedLibrariesDependencies)928 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibrariesDependencies) {
929 // Setup the context.
930 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
931 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
932 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
933 std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
934
935 std::string context_spec =
936 "PCL[" + CreateClassPath(classpath_dex_a) + "]{" +
937 "PCL[" + CreateClassPath(classpath_dex_b) + "]{" +
938 "PCL[" + CreateClassPath(classpath_dex_c) + "]}};" +
939 "PCL[" + CreateClassPath(classpath_dex_d) + "]";
940
941 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
942 ASSERT_TRUE(context->OpenDexFiles());
943
944 // Setup the compilation sources.
945 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
946 std::vector<const DexFile*> compilation_sources_raw =
947 MakeNonOwningPointerVector(compilation_sources);
948
949 // Create the class loader.
950 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
951 ASSERT_TRUE(jclass_loader != nullptr);
952
953 // Verify the class loader.
954 ScopedObjectAccess soa(Thread::Current());
955
956 StackHandleScope<6> hs(soa.Self());
957 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
958 soa.Decode<mirror::ClassLoader>(jclass_loader));
959
960 // For the first class loader the class path dex files must come first and then the
961 // compilation sources.
962 std::vector<const DexFile*> class_loader_1_dex_files =
963 MakeNonOwningPointerVector(classpath_dex_a);
964 for (auto& dex : compilation_sources_raw) {
965 class_loader_1_dex_files.push_back(dex);
966 }
967 VerifyClassLoaderDexFiles(soa,
968 class_loader_1,
969 WellKnownClasses::dalvik_system_PathClassLoader,
970 class_loader_1_dex_files);
971
972 // Verify its shared library.
973 ArtField* field =
974 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
975 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader_1.Get());
976 ASSERT_TRUE(raw_shared_libraries != nullptr);
977
978 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries(
979 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
980 ASSERT_EQ(shared_libraries->GetLength(), 1);
981
982 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(shared_libraries->Get(0));
983 std::vector<const DexFile*> class_loader_2_dex_files =
984 MakeNonOwningPointerVector(classpath_dex_b);
985 VerifyClassLoaderDexFiles(soa,
986 class_loader_2,
987 WellKnownClasses::dalvik_system_PathClassLoader,
988 class_loader_2_dex_files);
989
990 // Verify the shared library dependency of the shared library.
991 raw_shared_libraries = field->GetObject(class_loader_2.Get());
992 ASSERT_TRUE(raw_shared_libraries != nullptr);
993
994 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_2(
995 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
996 ASSERT_EQ(shared_libraries_2->GetLength(), 1);
997
998 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(shared_libraries_2->Get(0));
999 std::vector<const DexFile*> class_loader_3_dex_files =
1000 MakeNonOwningPointerVector(classpath_dex_c);
1001 VerifyClassLoaderDexFiles(soa,
1002 class_loader_3,
1003 WellKnownClasses::dalvik_system_PathClassLoader,
1004 class_loader_3_dex_files);
1005 raw_shared_libraries = field->GetObject(class_loader_3.Get());
1006 ASSERT_TRUE(raw_shared_libraries == nullptr);
1007
1008 // Verify the parent.
1009 Handle<mirror::ClassLoader> class_loader_4 = hs.NewHandle(class_loader_1->GetParent());
1010 std::vector<const DexFile*> class_loader_4_dex_files =
1011 MakeNonOwningPointerVector(classpath_dex_d);
1012 VerifyClassLoaderDexFiles(soa,
1013 class_loader_4,
1014 WellKnownClasses::dalvik_system_PathClassLoader,
1015 class_loader_4_dex_files);
1016 raw_shared_libraries = field->GetObject(class_loader_4.Get());
1017 ASSERT_TRUE(raw_shared_libraries == nullptr);
1018
1019 // Class loaders should have the BootClassLoader as a parent.
1020 ASSERT_TRUE(class_loader_2->GetParent()->GetClass() ==
1021 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
1022 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
1023 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
1024 ASSERT_TRUE(class_loader_4->GetParent()->GetClass() ==
1025 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
1026 }
1027
TEST_F(ClassLoaderContextTest,RemoveSourceLocations)1028 TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
1029 std::unique_ptr<ClassLoaderContext> context =
1030 ClassLoaderContext::Create("PCL[a.dex]");
1031 dchecked_vector<std::string> classpath_dex;
1032 classpath_dex.push_back("a.dex");
1033 dchecked_vector<std::string> compilation_sources;
1034 compilation_sources.push_back("src.dex");
1035
1036 // Nothing should be removed.
1037 ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
1038 VerifyClassLoaderPCL(context.get(), 0, "a.dex");
1039 // Classes should be removed.
1040 ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
1041 VerifyClassLoaderPCL(context.get(), 0, "");
1042 }
1043
TEST_F(ClassLoaderContextTest,CreateClassLoaderWithSameSharedLibraries)1044 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSameSharedLibraries) {
1045 // Setup the context.
1046 std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
1047 std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
1048 std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
1049
1050 std::string context_spec =
1051 "PCL[" + CreateClassPath(classpath_dex_a) + "]{" +
1052 "PCL[" + CreateClassPath(classpath_dex_b) + "]};" +
1053 "PCL[" + CreateClassPath(classpath_dex_c) + "]{" +
1054 "PCL[" + CreateClassPath(classpath_dex_b) + "]}";
1055
1056 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
1057 ASSERT_TRUE(context->OpenDexFiles());
1058
1059 // Setup the compilation sources.
1060 std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
1061 std::vector<const DexFile*> compilation_sources_raw =
1062 MakeNonOwningPointerVector(compilation_sources);
1063
1064 // Create the class loader.
1065 jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
1066 ASSERT_TRUE(jclass_loader != nullptr);
1067
1068 // Verify the class loader.
1069 ScopedObjectAccess soa(Thread::Current());
1070
1071 StackHandleScope<6> hs(soa.Self());
1072 Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
1073 soa.Decode<mirror::ClassLoader>(jclass_loader));
1074
1075 // For the first class loader the class path dex files must come first and then the
1076 // compilation sources.
1077 std::vector<const DexFile*> class_loader_1_dex_files =
1078 MakeNonOwningPointerVector(classpath_dex_a);
1079 for (auto& dex : compilation_sources_raw) {
1080 class_loader_1_dex_files.push_back(dex);
1081 }
1082 VerifyClassLoaderDexFiles(soa,
1083 class_loader_1,
1084 WellKnownClasses::dalvik_system_PathClassLoader,
1085 class_loader_1_dex_files);
1086
1087 // Verify its shared library.
1088 ArtField* field =
1089 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders);
1090 ObjPtr<mirror::Object> raw_shared_libraries = field->GetObject(class_loader_1.Get());
1091 ASSERT_TRUE(raw_shared_libraries != nullptr);
1092
1093 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries(
1094 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
1095 ASSERT_EQ(shared_libraries->GetLength(), 1);
1096
1097 Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(shared_libraries->Get(0));
1098 std::vector<const DexFile*> class_loader_2_dex_files =
1099 MakeNonOwningPointerVector(classpath_dex_b);
1100 VerifyClassLoaderDexFiles(soa,
1101 class_loader_2,
1102 WellKnownClasses::dalvik_system_PathClassLoader,
1103 class_loader_2_dex_files);
1104
1105 // Verify the parent.
1106 Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_1->GetParent());
1107 std::vector<const DexFile*> class_loader_3_dex_files =
1108 MakeNonOwningPointerVector(classpath_dex_c);
1109 VerifyClassLoaderDexFiles(soa,
1110 class_loader_3,
1111 WellKnownClasses::dalvik_system_PathClassLoader,
1112 class_loader_3_dex_files);
1113
1114 // Verify its shared library is the same as the child.
1115 raw_shared_libraries = field->GetObject(class_loader_3.Get());
1116 ASSERT_TRUE(raw_shared_libraries != nullptr);
1117 Handle<mirror::ObjectArray<mirror::ClassLoader>> shared_libraries_2(
1118 hs.NewHandle(raw_shared_libraries->AsObjectArray<mirror::ClassLoader>()));
1119 ASSERT_EQ(shared_libraries_2->GetLength(), 1);
1120 ASSERT_OBJ_PTR_EQ(shared_libraries_2->Get(0), class_loader_2.Get());
1121
1122 // Class loaders should have the BootClassLoader as a parent.
1123 ASSERT_TRUE(class_loader_2->GetParent()->GetClass() ==
1124 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
1125 ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
1126 soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
1127 }
1128
TEST_F(ClassLoaderContextTest,EncodeInOatFile)1129 TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
1130 std::string dex1_name = GetTestDexFileName("Main");
1131 std::string dex2_name = GetTestDexFileName("MyClass");
1132 std::unique_ptr<ClassLoaderContext> context =
1133 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
1134 ASSERT_TRUE(context->OpenDexFiles());
1135
1136 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
1137 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
1138 std::string encoding = context->EncodeContextForOatFile("");
1139 std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
1140 CreateClassPathWithChecksums(dex2) + "]";
1141 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
1142 }
1143
TEST_F(ClassLoaderContextTest,EncodeInOatFileIMC)1144 TEST_F(ClassLoaderContextTest, EncodeInOatFileIMC) {
1145 jobject class_loader_a = LoadDexInPathClassLoader("Main", nullptr);
1146 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("MyClass", class_loader_a);
1147
1148 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1149 ASSERT_TRUE(context->OpenDexFiles());
1150
1151 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
1152 std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
1153 ASSERT_EQ(dex2.size(), 1u);
1154
1155 std::string encoding = context->EncodeContextForOatFile("");
1156 std::string expected_encoding = "IMC[<unknown>*" + std::to_string(dex2[0]->GetLocationChecksum())
1157 + "];PCL[" + CreateClassPathWithChecksums(dex1) + "]";
1158 ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
1159 }
1160
TEST_F(ClassLoaderContextTest,EncodeForDex2oat)1161 TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
1162 std::string dex1_name = GetTestDexFileName("Main");
1163 std::string dex2_name = GetTestDexFileName("MultiDex");
1164 std::unique_ptr<ClassLoaderContext> context =
1165 ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
1166 ASSERT_TRUE(context->OpenDexFiles());
1167
1168 std::string encoding = context->EncodeContextForDex2oat("");
1169 std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
1170 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
1171 }
1172
TEST_F(ClassLoaderContextTest,EncodeForDex2oatIMC)1173 TEST_F(ClassLoaderContextTest, EncodeForDex2oatIMC) {
1174 jobject class_loader_a = LoadDexInPathClassLoader("Main", nullptr);
1175 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("MyClass", class_loader_a);
1176
1177 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1178 ASSERT_TRUE(context->OpenDexFiles());
1179
1180 std::string encoding = context->EncodeContextForDex2oat("");
1181 std::string expected_encoding = "IMC[<unknown>];PCL[" + GetTestDexFileName("Main") + "]";
1182 ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
1183 }
1184
TEST_F(ClassLoaderContextTest,EncodeContextsSinglePath)1185 TEST_F(ClassLoaderContextTest, EncodeContextsSinglePath) {
1186 jobject class_loader = LoadDexInPathClassLoader("Main", nullptr);
1187 std::unique_ptr<ClassLoaderContext> context =
1188 CreateContextForClassLoader(class_loader);
1189
1190 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1191 ASSERT_EQ(1u, encodings.size());
1192 ASSERT_EQ("PCL[]", encodings.at(GetTestDexFileName("Main")));
1193 }
1194
TEST_F(ClassLoaderContextTest,EncodeContextsMultiDex)1195 TEST_F(ClassLoaderContextTest, EncodeContextsMultiDex) {
1196 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
1197 std::unique_ptr<ClassLoaderContext> context =
1198 CreateContextForClassLoader(class_loader);
1199
1200 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1201 ASSERT_EQ(1u, encodings.size());
1202 ASSERT_EQ("PCL[]", encodings.at(GetTestDexFileName("MultiDex")));
1203 }
1204
TEST_F(ClassLoaderContextTest,EncodeContextsRepeatedMultiDex)1205 TEST_F(ClassLoaderContextTest, EncodeContextsRepeatedMultiDex) {
1206 jobject top_class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
1207 jobject middle_class_loader =
1208 LoadDexInPathClassLoader("Main", top_class_loader);
1209 jobject bottom_class_loader =
1210 LoadDexInPathClassLoader("MultiDex", middle_class_loader);
1211 std::unique_ptr<ClassLoaderContext> context =
1212 CreateContextForClassLoader(bottom_class_loader);
1213
1214 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1215 ASSERT_EQ(1u, encodings.size());
1216
1217 std::string main_dex_name = GetTestDexFileName("Main");
1218 std::string multidex_dex_name = GetTestDexFileName("MultiDex");
1219 ASSERT_EQ(
1220 "PCL[];PCL[" + main_dex_name + "];PCL[" + multidex_dex_name + "]",
1221 encodings.at(multidex_dex_name));
1222 }
1223
TEST_F(ClassLoaderContextTest,EncodeContextsSinglePathWithShared)1224 TEST_F(ClassLoaderContextTest, EncodeContextsSinglePathWithShared) {
1225 jobject class_loader_a = LoadDexInPathClassLoader("MyClass", nullptr);
1226
1227 ScopedObjectAccess soa(Thread::Current());
1228 StackHandleScope<1> hs(soa.Self());
1229 Handle<mirror::ObjectArray<mirror::ClassLoader>> libraries = hs.NewHandle(
1230 mirror::ObjectArray<mirror::ClassLoader>::Alloc(
1231 soa.Self(),
1232 GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
1233 1));
1234 libraries->Set(0, soa.Decode<mirror::ClassLoader>(class_loader_a));
1235
1236 jobject class_loader_b = LoadDexInPathClassLoader(
1237 "Main", nullptr, soa.AddLocalReference<jobject>(libraries.Get()));
1238
1239 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1240
1241 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1242 ASSERT_EQ(1u, encodings.size());
1243 ASSERT_EQ(
1244 "PCL[]{PCL[" + GetTestDexFileName("MyClass") + "]}",
1245 encodings.at(GetTestDexFileName("Main")));
1246 }
1247
TEST_F(ClassLoaderContextTest,EncodeContextsMultiplePaths)1248 TEST_F(ClassLoaderContextTest, EncodeContextsMultiplePaths) {
1249 jobject class_loader = LoadDexInPathClassLoader(
1250 std::vector<std::string>{ "Main", "MultiDex"}, nullptr);
1251
1252 std::unique_ptr<ClassLoaderContext> context =
1253 CreateContextForClassLoader(class_loader);
1254
1255 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1256 ASSERT_EQ(2u, encodings.size());
1257 ASSERT_EQ("PCL[]", encodings.at(GetTestDexFileName("Main")));
1258 ASSERT_EQ(
1259 "PCL[" + GetTestDexFileName("Main") + "]", encodings.at(GetTestDexFileName("MultiDex")));
1260 }
1261
TEST_F(ClassLoaderContextTest,EncodeContextsMultiplePathsWithShared)1262 TEST_F(ClassLoaderContextTest, EncodeContextsMultiplePathsWithShared) {
1263 jobject class_loader_a = LoadDexInPathClassLoader("MyClass", nullptr);
1264
1265 ScopedObjectAccess soa(Thread::Current());
1266 StackHandleScope<1> hs(soa.Self());
1267 Handle<mirror::ObjectArray<mirror::ClassLoader>> libraries = hs.NewHandle(
1268 mirror::ObjectArray<mirror::ClassLoader>::Alloc(
1269 soa.Self(),
1270 GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
1271 1));
1272 libraries->Set(0, soa.Decode<mirror::ClassLoader>(class_loader_a));
1273
1274 jobject class_loader_b = LoadDexInPathClassLoader(
1275 std::vector<std::string> { "Main", "MultiDex" },
1276 nullptr, soa.AddLocalReference<jobject>(libraries.Get()));
1277
1278 std::unique_ptr<ClassLoaderContext> context =
1279 CreateContextForClassLoader(class_loader_b);
1280
1281 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1282 ASSERT_EQ(2u, encodings.size());
1283 const std::string context_suffix =
1284 "{PCL[" + GetTestDexFileName("MyClass") + "]}";
1285 ASSERT_EQ("PCL[]" + context_suffix, encodings.at(GetTestDexFileName("Main")));
1286 ASSERT_EQ(
1287 "PCL[" + GetTestDexFileName("Main") + "]" + context_suffix,
1288 encodings.at(GetTestDexFileName("MultiDex")));
1289 }
1290
TEST_F(ClassLoaderContextTest,EncodeContextsIMC)1291 TEST_F(ClassLoaderContextTest, EncodeContextsIMC) {
1292 jobject class_loader_a = LoadDexInPathClassLoader("Main", nullptr);
1293 jobject class_loader_b =
1294 LoadDexInInMemoryDexClassLoader("MyClass", class_loader_a);
1295
1296 std::unique_ptr<ClassLoaderContext> context =
1297 CreateContextForClassLoader(class_loader_b);
1298
1299 std::map<std::string, std::string> encodings = context->EncodeClassPathContexts("");
1300 ASSERT_EQ(1u, encodings.size());
1301 ASSERT_EQ(
1302 "IMC[];PCL[" + GetTestDexFileName("Main") + "]",
1303 encodings.at("<unknown>"));
1304 }
1305
TEST_F(ClassLoaderContextTest,EncodeContextsForSingleDex)1306 TEST_F(ClassLoaderContextTest, EncodeContextsForSingleDex) {
1307 jobject class_loader = LoadDexInPathClassLoader("Main", nullptr);
1308 std::map<std::string, std::string> encodings =
1309 ClassLoaderContext::EncodeClassPathContextsForClassLoader(class_loader);
1310 ASSERT_EQ(1u, encodings.size());
1311 ASSERT_EQ("PCL[]", encodings.at(GetTestDexFileName("Main")));
1312 }
1313
CreateForeignClassLoader()1314 static jobject CreateForeignClassLoader() {
1315 ScopedObjectAccess soa(Thread::Current());
1316 JNIEnv* env = soa.Env();
1317
1318 // We cannot instantiate a ClassLoader directly, so instead we allocate an Object to represent
1319 // our foreign ClassLoader (this works because the runtime does proper instanceof checks before
1320 // operating on this object.
1321 jmethodID ctor = env->GetMethodID(WellKnownClasses::java_lang_Object, "<init>", "()V");
1322 return env->NewObject(WellKnownClasses::java_lang_Object, ctor);
1323 }
1324
TEST_F(ClassLoaderContextTest,EncodeContextsForUnsupportedBase)1325 TEST_F(ClassLoaderContextTest, EncodeContextsForUnsupportedBase) {
1326 std::map<std::string, std::string> empty;
1327 ASSERT_EQ(
1328 empty, ClassLoaderContext::EncodeClassPathContextsForClassLoader(CreateForeignClassLoader()));
1329 }
1330
TEST_F(ClassLoaderContextTest,EncodeContextsForUnsupportedChain)1331 TEST_F(ClassLoaderContextTest, EncodeContextsForUnsupportedChain) {
1332 jobject class_loader = LoadDexInPathClassLoader("Main", CreateForeignClassLoader());
1333 std::map<std::string, std::string> encodings =
1334 ClassLoaderContext::EncodeClassPathContextsForClassLoader(class_loader);
1335 ASSERT_EQ(1u, encodings.size());
1336 ASSERT_EQ(
1337 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding,
1338 encodings.at(GetTestDexFileName("Main")));
1339 }
1340
TEST_F(ClassLoaderContextTest,EncodeContextsForUnsupportedChainMultiPath)1341 TEST_F(ClassLoaderContextTest, EncodeContextsForUnsupportedChainMultiPath) {
1342 jobject class_loader = LoadDexInPathClassLoader(std::vector<std::string> { "Main", "MyClass" },
1343 CreateForeignClassLoader());
1344 std::map<std::string, std::string> encodings =
1345 ClassLoaderContext::EncodeClassPathContextsForClassLoader(class_loader);
1346 ASSERT_EQ(2u, encodings.size());
1347 ASSERT_EQ(
1348 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding,
1349 encodings.at(GetTestDexFileName("Main")));
1350 ASSERT_EQ(
1351 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding,
1352 encodings.at(GetTestDexFileName("MyClass")));
1353 }
1354
TEST_F(ClassLoaderContextTest,EncodeContextsForUnsupportedChainMultiDex)1355 TEST_F(ClassLoaderContextTest, EncodeContextsForUnsupportedChainMultiDex) {
1356 jobject class_loader = LoadDexInPathClassLoader("MultiDex", CreateForeignClassLoader());
1357 std::map<std::string, std::string> encodings =
1358 ClassLoaderContext::EncodeClassPathContextsForClassLoader(class_loader);
1359 ASSERT_EQ(1u, encodings.size());
1360 ASSERT_EQ(
1361 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding,
1362 encodings.at(GetTestDexFileName("MultiDex")));
1363 }
1364
TEST_F(ClassLoaderContextTest,IsValidEncoding)1365 TEST_F(ClassLoaderContextTest, IsValidEncoding) {
1366 ASSERT_TRUE(ClassLoaderContext::IsValidEncoding("PCL[]"));
1367 ASSERT_TRUE(ClassLoaderContext::IsValidEncoding("PCL[foo.dex]"));
1368 ASSERT_TRUE(ClassLoaderContext::IsValidEncoding("PCL[foo.dex];PCL[bar.dex]"));
1369 ASSERT_TRUE(ClassLoaderContext::IsValidEncoding("DLC[];PCL[bar.dex]"));
1370 ASSERT_TRUE(
1371 ClassLoaderContext::IsValidEncoding(
1372 ClassLoaderContext::kUnsupportedClassLoaderContextEncoding));
1373 ASSERT_FALSE(ClassLoaderContext::IsValidEncoding("not_valid"));
1374 ASSERT_FALSE(ClassLoaderContext::IsValidEncoding("[]"));
1375 ASSERT_FALSE(ClassLoaderContext::IsValidEncoding("FCL[]"));
1376 ASSERT_FALSE(ClassLoaderContext::IsValidEncoding("foo.dex:bar.dex"));
1377 }
1378
1379 // TODO(calin) add a test which creates the context for a class loader together with dex_elements.
TEST_F(ClassLoaderContextTest,CreateContextForClassLoader)1380 TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
1381 // The chain is
1382 // ClassLoaderA (PathClassLoader)
1383 // ^
1384 // |
1385 // ClassLoaderB (DelegateLastClassLoader)
1386 // ^
1387 // |
1388 // ClassLoaderC (PathClassLoader)
1389 // ^
1390 // |
1391 // ClassLoaderD (DelegateLastClassLoader)
1392
1393 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1394 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
1395 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
1396 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
1397
1398 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
1399
1400 VerifyContextForClassLoader(context.get());
1401 VerifyContextSize(context.get(), 4);
1402
1403 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
1404 VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
1405 VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
1406 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
1407 }
1408
TEST_F(ClassLoaderContextTest,CreateContextForClassLoaderIMC)1409 TEST_F(ClassLoaderContextTest, CreateContextForClassLoaderIMC) {
1410 // The chain is
1411 // ClassLoaderA (PathClassLoader)
1412 // ^
1413 // |
1414 // ClassLoaderB (InMemoryDexClassLoader)
1415 // ^
1416 // |
1417 // ClassLoaderC (InMemoryDexClassLoader)
1418 // ^
1419 // |
1420 // ClassLoaderD (DelegateLastClassLoader)
1421
1422 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1423 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("ForClassLoaderB", class_loader_a);
1424 jobject class_loader_c = LoadDexInInMemoryDexClassLoader("ForClassLoaderC", class_loader_b);
1425 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
1426
1427 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
1428
1429 VerifyContextForClassLoader(context.get());
1430 VerifyContextSize(context.get(), 4);
1431
1432 VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
1433 VerifyClassLoaderIMCFromTestDex(context.get(), 1, "ForClassLoaderC");
1434 VerifyClassLoaderIMCFromTestDex(context.get(), 2, "ForClassLoaderB");
1435 VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
1436 }
1437
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatch)1438 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
1439 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
1440 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1441 // Pretend that we successfully open the dex files to pass the DCHECKS.
1442 // (as it's much easier to test all the corner cases without relying on actual dex files).
1443 PretendContextOpenedDexFilesForChecksums(context.get());
1444
1445 VerifyContextSize(context.get(), 2);
1446 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
1447 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
1448
1449 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1450 ClassLoaderContext::VerificationResult::kVerifies);
1451
1452 std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
1453 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_class_loader_type),
1454 ClassLoaderContext::VerificationResult::kMismatch);
1455
1456 std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
1457 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_class_loader_order),
1458 ClassLoaderContext::VerificationResult::kMismatch);
1459
1460 std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
1461 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_classpath_order),
1462 ClassLoaderContext::VerificationResult::kMismatch);
1463
1464 std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
1465 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_checksum),
1466 ClassLoaderContext::VerificationResult::kMismatch);
1467
1468 std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
1469 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader),
1470 ClassLoaderContext::VerificationResult::kMismatch);
1471
1472 std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
1473 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_extra_classpath),
1474 ClassLoaderContext::VerificationResult::kMismatch);
1475
1476 std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
1477 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_spec),
1478 ClassLoaderContext::VerificationResult::kMismatch);
1479 }
1480
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextWithIMCMatch)1481 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextWithIMCMatch) {
1482 std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];IMC[<unknown>*111]";
1483 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1484 // Pretend that we successfully open the dex files to pass the DCHECKS.
1485 // (as it's much easier to test all the corner cases without relying on actual dex files).
1486 PretendContextOpenedDexFiles(context.get());
1487
1488 VerifyContextSize(context.get(), 3);
1489 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
1490 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
1491 VerifyClassLoaderIMC(context.get(), 2, "<unknown>");
1492
1493 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1494 ClassLoaderContext::VerificationResult::kVerifies);
1495 }
1496
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchWithSL)1497 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchWithSL) {
1498 std::string context_spec =
1499 "PCL[a.dex*123:b.dex*456]{PCL[d.dex*321];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999]}"
1500 ";DLC[c.dex*890]";
1501 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1502 // Pretend that we successfully open the dex files to pass the DCHECKS.
1503 // (as it's much easier to test all the corner cases without relying on actual dex files).
1504 PretendContextOpenedDexFiles(context.get());
1505
1506 VerifyContextSize(context.get(), 2);
1507 VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
1508 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
1509 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, "d.dex");
1510 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 1, "f.dex:g.dex");
1511
1512 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1513 ClassLoaderContext::VerificationResult::kVerifies);
1514
1515 std::string wrong_class_loader_type =
1516 "PCL[a.dex*123:b.dex*456]{DLC[d.dex*321];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999]}"
1517 ";DLC[c.dex*890]";
1518 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_class_loader_type),
1519 ClassLoaderContext::VerificationResult::kMismatch);
1520
1521 std::string wrong_class_loader_order =
1522 "PCL[a.dex*123:b.dex*456]{PCL[f.dex#098:g.dex#999}#PCL[d.dex*321];PCL[e.dex*654]}"
1523 ";DLC[c.dex*890]";
1524 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_class_loader_order),
1525 ClassLoaderContext::VerificationResult::kMismatch);
1526
1527 std::string wrong_classpath_order =
1528 "PCL[a.dex*123:b.dex*456]{PCL[d.dex*321];PCL[e.dex*654]#PCL[g.dex*999:f.dex*098]}"
1529 ";DLC[c.dex*890]";
1530 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_classpath_order),
1531 ClassLoaderContext::VerificationResult::kMismatch);
1532
1533 std::string wrong_checksum =
1534 "PCL[a.dex*123:b.dex*456]{PCL[d.dex*333];PCL[e.dex*654]#PCL[g.dex*999:f.dex*098]}"
1535 ";DLC[c.dex*890]";
1536 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_checksum),
1537 ClassLoaderContext::VerificationResult::kMismatch);
1538
1539 std::string wrong_extra_class_loader =
1540 "PCL[a.dex*123:b.dex*456]"
1541 "{PCL[d.dex*321];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999];PCL[i.dex#444]}"
1542 ";DLC[c.dex*890]";
1543 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader),
1544 ClassLoaderContext::VerificationResult::kMismatch);
1545
1546 std::string wrong_extra_classpath =
1547 "PCL[a.dex*123:b.dex*456]{PCL[d.dex*321:i.dex#444];PCL[e.dex*654]#PCL[f.dex*098:g.dex*999]}"
1548 ";DLC[c.dex*890]";
1549 ASSERT_EQ(context->VerifyClassLoaderContextMatch(wrong_extra_classpath),
1550 ClassLoaderContext::VerificationResult::kMismatch);
1551 }
1552
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchWithIMCSL)1553 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchWithIMCSL) {
1554 std::string context_spec =
1555 "IMC[<unknown>*123:<unknown>*456]"
1556 "{IMC[<unknown>*321];IMC[<unknown>*654]#IMC[<unknown>*098:<unknown>*999]};"
1557 "DLC[c.dex*890]";
1558 std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
1559 // Pretend that we successfully open the dex files to pass the DCHECKS.
1560 // (as it's much easier to test all the corner cases without relying on actual dex files).
1561 PretendContextOpenedDexFiles(context.get());
1562
1563 VerifyContextSize(context.get(), 2);
1564 VerifyClassLoaderIMC(context.get(), 0, "<unknown>:<unknown>");
1565 VerifyClassLoaderDLC(context.get(), 1, "c.dex");
1566 VerifyClassLoaderSharedLibraryIMC(context.get(), 0, 0, "<unknown>");
1567 VerifyClassLoaderSharedLibraryIMC(context.get(), 0, 1, "<unknown>:<unknown>");
1568
1569 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_spec),
1570 ClassLoaderContext::VerificationResult::kVerifies);
1571 }
1572
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchAfterEncoding)1573 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
1574 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1575 jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
1576 jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
1577 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
1578
1579 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
1580
1581 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
1582 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_no_base_dir),
1583 ClassLoaderContext::VerificationResult::kVerifies);
1584
1585 std::string dex_location = GetTestDexFileName("ForClassLoaderA");
1586 size_t pos = dex_location.rfind('/');
1587 ASSERT_NE(std::string::npos, pos);
1588 std::string parent = dex_location.substr(0, pos);
1589
1590 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
1591 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
1592 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_base_dir),
1593 ClassLoaderContext::VerificationResult::kVerifies);
1594 }
1595
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchAfterEncodingIMC)1596 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingIMC) {
1597 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1598 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("ForClassLoaderB", class_loader_a);
1599 jobject class_loader_c = LoadDexInInMemoryDexClassLoader("ForClassLoaderC", class_loader_b);
1600 jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
1601
1602 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
1603
1604 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
1605 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_no_base_dir),
1606 ClassLoaderContext::VerificationResult::kVerifies);
1607
1608 std::string dex_location = GetTestDexFileName("ForClassLoaderA");
1609 size_t pos = dex_location.rfind('/');
1610 ASSERT_NE(std::string::npos, pos);
1611 std::string parent = dex_location.substr(0, pos);
1612
1613 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
1614 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
1615 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_base_dir),
1616 ClassLoaderContext::VerificationResult::kVerifies);
1617 }
1618
TEST_F(ClassLoaderContextTest,VerifyClassLoaderContextMatchAfterEncodingMultidex)1619 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
1620 jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
1621
1622 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
1623
1624 std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
1625 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_no_base_dir),
1626 ClassLoaderContext::VerificationResult::kVerifies);
1627
1628 std::string dex_location = GetTestDexFileName("MultiDex");
1629 size_t pos = dex_location.rfind('/');
1630 ASSERT_NE(std::string::npos, pos);
1631 std::string parent = dex_location.substr(0, pos);
1632
1633 std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
1634 ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
1635 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context_with_base_dir),
1636 ClassLoaderContext::VerificationResult::kVerifies);
1637 }
1638
TEST_F(ClassLoaderContextTest,CreateContextForClassLoaderWithSharedLibraries)1639 TEST_F(ClassLoaderContextTest, CreateContextForClassLoaderWithSharedLibraries) {
1640 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1641
1642 ScopedObjectAccess soa(Thread::Current());
1643 StackHandleScope<1> hs(soa.Self());
1644 Handle<mirror::ObjectArray<mirror::ClassLoader>> libraries = hs.NewHandle(
1645 mirror::ObjectArray<mirror::ClassLoader>::Alloc(
1646 soa.Self(),
1647 GetClassRoot<mirror::ObjectArray<mirror::ClassLoader>>(),
1648 1));
1649 libraries->Set(0, soa.Decode<mirror::ClassLoader>(class_loader_a));
1650
1651 jobject class_loader_b = LoadDexInPathClassLoader(
1652 "ForClassLoaderB", nullptr, soa.AddLocalReference<jobject>(libraries.Get()));
1653
1654 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1655 ASSERT_TRUE(context != nullptr);
1656 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles("ForClassLoaderB");
1657 VerifyClassLoaderPCL(context.get(), 0, dex_files[0]->GetLocation());
1658 dex_files = OpenTestDexFiles("ForClassLoaderA");
1659 VerifyClassLoaderSharedLibraryPCL(context.get(), 0, 0, dex_files[0]->GetLocation());
1660
1661 ASSERT_EQ(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")),
1662 ClassLoaderContext::VerificationResult::kVerifies);
1663 }
1664
TEST_F(ClassLoaderContextTest,CheckForDuplicateDexFilesNotFoundSingleCL)1665 TEST_F(ClassLoaderContextTest, CheckForDuplicateDexFilesNotFoundSingleCL) {
1666 jobject class_loader = LoadDexInPathClassLoader("Main", nullptr);
1667
1668 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
1669
1670 std::set<const DexFile*> result = context->CheckForDuplicateDexFiles(
1671 std::vector<const DexFile*>());
1672 ASSERT_EQ(0u, result.size());
1673
1674 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("ForClassLoaderA");
1675 std::vector<const DexFile*> dex1_raw = MakeNonOwningPointerVector(dex1);
1676 result = context->CheckForDuplicateDexFiles(dex1_raw);
1677 ASSERT_EQ(0u, result.size());
1678 }
1679
TEST_F(ClassLoaderContextTest,CheckForDuplicateDexFilesFound)1680 TEST_F(ClassLoaderContextTest, CheckForDuplicateDexFilesFound) {
1681 jobject class_loader = LoadDexInPathClassLoader(std::vector<std::string> { "Main", "Main" }, nullptr);
1682
1683 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
1684
1685 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
1686 std::vector<const DexFile*> dex1_raw = MakeNonOwningPointerVector(dex1);
1687 std::set<const DexFile*> result = context->CheckForDuplicateDexFiles(dex1_raw);
1688 ASSERT_EQ(1u, result.size()) << context->EncodeContextForOatFile("");
1689 ASSERT_EQ(dex1_raw[0], *(result.begin()));
1690 }
1691
1692
TEST_F(ClassLoaderContextTest,CheckForDuplicateCrossCLNotFound)1693 TEST_F(ClassLoaderContextTest, CheckForDuplicateCrossCLNotFound) {
1694 jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
1695 jobject class_loader_b = LoadDexInInMemoryDexClassLoader("ForClassLoaderB", class_loader_a);
1696
1697 std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_b);
1698
1699 std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("ForClassLoaderA");
1700 std::vector<const DexFile*> dex1_raw = MakeNonOwningPointerVector(dex1);
1701 std::set<const DexFile*> result = context->CheckForDuplicateDexFiles(dex1_raw);
1702 ASSERT_EQ(0u, result.size());
1703 }
1704
1705 } // namespace art
1706