Home | History | Annotate | Download | only in runtime
      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