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