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