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 "class_loader_context.h"
     18 
     19 #include <gtest/gtest.h>
     20 
     21 #include "android-base/strings.h"
     22 #include "base/dchecked_vector.h"
     23 #include "base/stl_util.h"
     24 #include "class_linker.h"
     25 #include "common_runtime_test.h"
     26 #include "dex/dex_file.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   enum class LocationCheck {
     75     kEquals,
     76     kEndsWith
     77   };
     78   enum class BaseLocationCheck {
     79     kEquals,
     80     kEndsWith
     81   };
     82 
     83   static bool IsAbsoluteLocation(const std::string& location) {
     84     return !location.empty() && location[0] == '/';
     85   }
     86 
     87   void VerifyOpenDexFiles(
     88       ClassLoaderContext* context,
     89       size_t index,
     90       std::vector<std::unique_ptr<const DexFile>>* all_dex_files) {
     91     ASSERT_TRUE(context != nullptr);
     92     ASSERT_TRUE(context->dex_files_open_attempted_);
     93     ASSERT_TRUE(context->dex_files_open_result_);
     94     ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
     95     ASSERT_EQ(all_dex_files->size(), info.classpath.size());
     96     ASSERT_EQ(all_dex_files->size(), info.opened_dex_files.size());
     97     size_t cur_open_dex_index = 0;
     98     for (size_t k = 0; k < all_dex_files->size(); k++) {
     99       std::unique_ptr<const DexFile>& opened_dex_file =
    100             info.opened_dex_files[cur_open_dex_index++];
    101       std::unique_ptr<const DexFile>& expected_dex_file = (*all_dex_files)[k];
    102 
    103       std::string expected_location = expected_dex_file->GetLocation();
    104 
    105       const std::string& opened_location = opened_dex_file->GetLocation();
    106       if (!IsAbsoluteLocation(opened_location)) {
    107         // If the opened location is relative (it was open from a relative path without a
    108         // classpath_dir) it might not match the expected location which is absolute in tests).
    109         // So we compare the endings (the checksum will validate it's actually the same file).
    110         ASSERT_EQ(0, expected_location.compare(
    111             expected_location.length() - opened_location.length(),
    112             opened_location.length(),
    113             opened_location));
    114       } else {
    115         ASSERT_EQ(expected_location, opened_location);
    116       }
    117       ASSERT_EQ(expected_dex_file->GetLocationChecksum(), opened_dex_file->GetLocationChecksum());
    118       ASSERT_EQ(info.classpath[k], opened_location);
    119     }
    120   }
    121 
    122   std::unique_ptr<ClassLoaderContext> CreateContextForClassLoader(jobject class_loader) {
    123     return ClassLoaderContext::CreateContextForClassLoader(class_loader, nullptr);
    124   }
    125 
    126   std::unique_ptr<ClassLoaderContext> ParseContextWithChecksums(const std::string& context_spec) {
    127     std::unique_ptr<ClassLoaderContext> context(new ClassLoaderContext());
    128     if (!context->Parse(context_spec, /*parse_checksums*/ true)) {
    129       return nullptr;
    130     }
    131     return context;
    132   }
    133 
    134   void VerifyContextForClassLoader(ClassLoaderContext* context) {
    135     ASSERT_TRUE(context != nullptr);
    136     ASSERT_TRUE(context->dex_files_open_attempted_);
    137     ASSERT_TRUE(context->dex_files_open_result_);
    138     ASSERT_FALSE(context->owns_the_dex_files_);
    139     ASSERT_FALSE(context->special_shared_library_);
    140   }
    141 
    142   void VerifyClassLoaderDexFiles(ScopedObjectAccess& soa,
    143                                  Handle<mirror::ClassLoader> class_loader,
    144                                  jclass type,
    145                                  std::vector<const DexFile*>& expected_dex_files)
    146       REQUIRES_SHARED(Locks::mutator_lock_) {
    147     ASSERT_TRUE(class_loader->GetClass() == soa.Decode<mirror::Class>(type));
    148 
    149     std::vector<const DexFile*> class_loader_dex_files = GetDexFiles(soa, class_loader);
    150     ASSERT_EQ(expected_dex_files.size(), class_loader_dex_files.size());
    151 
    152     for (size_t i = 0; i < expected_dex_files.size(); i++) {
    153       ASSERT_EQ(expected_dex_files[i]->GetLocation(),
    154                 class_loader_dex_files[i]->GetLocation());
    155       ASSERT_EQ(expected_dex_files[i]->GetLocationChecksum(),
    156                 class_loader_dex_files[i]->GetLocationChecksum());
    157     }
    158   }
    159 
    160   void PretendContextOpenedDexFiles(ClassLoaderContext* context) {
    161     context->dex_files_open_attempted_ = true;
    162     context->dex_files_open_result_ = true;
    163   }
    164 
    165  private:
    166   void VerifyClassLoaderInfo(ClassLoaderContext* context,
    167                              size_t index,
    168                              ClassLoaderContext::ClassLoaderType type,
    169                              const std::string& classpath) {
    170     ASSERT_TRUE(context != nullptr);
    171     ASSERT_GT(context->class_loader_chain_.size(), index);
    172     ClassLoaderContext::ClassLoaderInfo& info = context->class_loader_chain_[index];
    173     ASSERT_EQ(type, info.type);
    174     std::vector<std::string> expected_classpath;
    175     Split(classpath, ':', &expected_classpath);
    176     ASSERT_EQ(expected_classpath, info.classpath);
    177   }
    178 
    179   void VerifyClassLoaderFromTestDex(ClassLoaderContext* context,
    180                                     size_t index,
    181                                     ClassLoaderContext::ClassLoaderType type,
    182                                     const std::string& test_name) {
    183     std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(test_name.c_str());
    184 
    185     VerifyClassLoaderInfo(context, index, type, GetTestDexFileName(test_name.c_str()));
    186     VerifyOpenDexFiles(context, index, &dex_files);
    187   }
    188 };
    189 
    190 TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
    191   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
    192   // An empty context should create a single empty PathClassLoader.
    193   VerifyContextSize(context.get(), 1);
    194   VerifyClassLoaderPCL(context.get(), 0, "");
    195 }
    196 
    197 TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
    198   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
    199   // An shared library context should have no class loader in the chain.
    200   VerifyContextSize(context.get(), 0);
    201 }
    202 
    203 TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
    204   std::unique_ptr<ClassLoaderContext> context =
    205       ClassLoaderContext::Create("PCL[a.dex]");
    206   VerifyContextSize(context.get(), 1);
    207   VerifyClassLoaderPCL(context.get(), 0, "a.dex");
    208 }
    209 
    210 TEST_F(ClassLoaderContextTest, ParseValidContextDLC) {
    211   std::unique_ptr<ClassLoaderContext> context =
    212       ClassLoaderContext::Create("DLC[a.dex]");
    213   VerifyContextSize(context.get(), 1);
    214   VerifyClassLoaderDLC(context.get(), 0, "a.dex");
    215 }
    216 
    217 TEST_F(ClassLoaderContextTest, ParseValidContextChain) {
    218   std::unique_ptr<ClassLoaderContext> context =
    219       ClassLoaderContext::Create("PCL[a.dex:b.dex];DLC[c.dex:d.dex];PCL[e.dex]");
    220   VerifyContextSize(context.get(), 3);
    221   VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
    222   VerifyClassLoaderDLC(context.get(), 1, "c.dex:d.dex");
    223   VerifyClassLoaderPCL(context.get(), 2, "e.dex");
    224 }
    225 
    226 TEST_F(ClassLoaderContextTest, ParseValidEmptyContextDLC) {
    227   std::unique_ptr<ClassLoaderContext> context =
    228       ClassLoaderContext::Create("DLC[]");
    229   VerifyContextSize(context.get(), 1);
    230   VerifyClassLoaderDLC(context.get(), 0, "");
    231 }
    232 
    233 TEST_F(ClassLoaderContextTest, ParseValidContextSpecialSymbol) {
    234   std::unique_ptr<ClassLoaderContext> context =
    235     ClassLoaderContext::Create(OatFile::kSpecialSharedLibrary);
    236   VerifyContextSize(context.get(), 0);
    237 }
    238 
    239 TEST_F(ClassLoaderContextTest, ParseInvalidValidContexts) {
    240   ASSERT_TRUE(nullptr == ClassLoaderContext::Create("ABC[a.dex]"));
    241   ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL"));
    242   ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex"));
    243   ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCLa.dex]"));
    244   ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL{a.dex}"));
    245   ASSERT_TRUE(nullptr == ClassLoaderContext::Create("PCL[a.dex];DLC[b.dex"));
    246 }
    247 
    248 TEST_F(ClassLoaderContextTest, OpenInvalidDexFiles) {
    249   std::unique_ptr<ClassLoaderContext> context =
    250       ClassLoaderContext::Create("PCL[does_not_exist.dex]");
    251   VerifyContextSize(context.get(), 1);
    252   ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, "."));
    253 }
    254 
    255 TEST_F(ClassLoaderContextTest, OpenValidDexFiles) {
    256   std::string multidex_name = GetTestDexFileName("MultiDex");
    257   std::string myclass_dex_name = GetTestDexFileName("MyClass");
    258   std::string dex_name = GetTestDexFileName("Main");
    259 
    260 
    261   std::unique_ptr<ClassLoaderContext> context =
    262       ClassLoaderContext::Create(
    263           "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
    264           "DLC[" + dex_name + "]");
    265 
    266   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
    267 
    268   VerifyContextSize(context.get(), 2);
    269 
    270   std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
    271   std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
    272   for (size_t i = 0; i < myclass_dex_files.size(); i++) {
    273     all_dex_files0.emplace_back(myclass_dex_files[i].release());
    274   }
    275   VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
    276 
    277   std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
    278   VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
    279 }
    280 
    281 // Creates a relative path from cwd to 'in'. Returns false if it cannot be done.
    282 // TODO We should somehow support this in all situations. b/72042237.
    283 static bool CreateRelativeString(const std::string& in, const char* cwd, std::string* out) {
    284   int cwd_len = strlen(cwd);
    285   if (!android::base::StartsWith(in, cwd) || (cwd_len < 1)) {
    286     return false;
    287   }
    288   bool contains_trailing_slash = (cwd[cwd_len - 1] == '/');
    289   int start_position = cwd_len + (contains_trailing_slash ? 0 : 1);
    290   *out = in.substr(start_position);
    291   return true;
    292 }
    293 
    294 TEST_F(ClassLoaderContextTest, OpenValidDexFilesRelative) {
    295   char cwd_buf[4096];
    296   if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
    297     PLOG(FATAL) << "Could not get working directory";
    298   }
    299   std::string multidex_name;
    300   std::string myclass_dex_name;
    301   std::string dex_name;
    302   if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
    303       !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
    304       !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
    305     LOG(ERROR) << "Test OpenValidDexFilesRelative cannot be run because target dex files have no "
    306                << "relative path.";
    307     SUCCEED();
    308     return;
    309   }
    310 
    311 
    312   std::unique_ptr<ClassLoaderContext> context =
    313       ClassLoaderContext::Create(
    314           "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
    315           "DLC[" + dex_name + "]");
    316 
    317   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, /*classpath_dir*/ ""));
    318 
    319   std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
    320   std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
    321   for (size_t i = 0; i < myclass_dex_files.size(); i++) {
    322     all_dex_files0.emplace_back(myclass_dex_files[i].release());
    323   }
    324   VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
    325 
    326   std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
    327   VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
    328 }
    329 
    330 TEST_F(ClassLoaderContextTest, OpenValidDexFilesClasspathDir) {
    331   char cwd_buf[4096];
    332   if (getcwd(cwd_buf, arraysize(cwd_buf)) == nullptr) {
    333     PLOG(FATAL) << "Could not get working directory";
    334   }
    335   std::string multidex_name;
    336   std::string myclass_dex_name;
    337   std::string dex_name;
    338   if (!CreateRelativeString(GetTestDexFileName("MultiDex"), cwd_buf, &multidex_name) ||
    339       !CreateRelativeString(GetTestDexFileName("MyClass"), cwd_buf, &myclass_dex_name) ||
    340       !CreateRelativeString(GetTestDexFileName("Main"), cwd_buf, &dex_name)) {
    341     LOG(ERROR) << "Test OpenValidDexFilesClasspathDir cannot be run because target dex files have "
    342                << "no relative path.";
    343     SUCCEED();
    344     return;
    345   }
    346   std::unique_ptr<ClassLoaderContext> context =
    347       ClassLoaderContext::Create(
    348           "PCL[" + multidex_name + ":" + myclass_dex_name + "];" +
    349           "DLC[" + dex_name + "]");
    350 
    351   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, cwd_buf));
    352 
    353   VerifyContextSize(context.get(), 2);
    354   std::vector<std::unique_ptr<const DexFile>> all_dex_files0 = OpenTestDexFiles("MultiDex");
    355   std::vector<std::unique_ptr<const DexFile>> myclass_dex_files = OpenTestDexFiles("MyClass");
    356   for (size_t i = 0; i < myclass_dex_files.size(); i++) {
    357     all_dex_files0.emplace_back(myclass_dex_files[i].release());
    358   }
    359   VerifyOpenDexFiles(context.get(), 0, &all_dex_files0);
    360 
    361   std::vector<std::unique_ptr<const DexFile>> all_dex_files1 = OpenTestDexFiles("Main");
    362   VerifyOpenDexFiles(context.get(), 1, &all_dex_files1);
    363 }
    364 
    365 TEST_F(ClassLoaderContextTest, OpenInvalidDexFilesMix) {
    366   std::string dex_name = GetTestDexFileName("Main");
    367   std::unique_ptr<ClassLoaderContext> context =
    368       ClassLoaderContext::Create("PCL[does_not_exist.dex];DLC[" + dex_name + "]");
    369   ASSERT_FALSE(context->OpenDexFiles(InstructionSet::kArm, ""));
    370 }
    371 
    372 TEST_F(ClassLoaderContextTest, CreateClassLoader) {
    373   std::string dex_name = GetTestDexFileName("Main");
    374   std::unique_ptr<ClassLoaderContext> context =
    375       ClassLoaderContext::Create("PCL[" + dex_name + "]");
    376   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
    377 
    378   std::vector<std::unique_ptr<const DexFile>> classpath_dex = OpenTestDexFiles("Main");
    379   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
    380 
    381   std::vector<const DexFile*> compilation_sources_raw =
    382       MakeNonOwningPointerVector(compilation_sources);
    383   jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
    384   ASSERT_TRUE(jclass_loader != nullptr);
    385 
    386   ScopedObjectAccess soa(Thread::Current());
    387 
    388   StackHandleScope<1> hs(soa.Self());
    389   Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
    390       soa.Decode<mirror::ClassLoader>(jclass_loader));
    391 
    392   ASSERT_TRUE(class_loader->GetClass() ==
    393       soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
    394   ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
    395       soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
    396 
    397   // For the first class loader the class path dex files must come first and then the
    398   // compilation sources.
    399   std::vector<const DexFile*> expected_classpath = MakeNonOwningPointerVector(classpath_dex);
    400   for (auto& dex : compilation_sources_raw) {
    401     expected_classpath.push_back(dex);
    402   }
    403 
    404   VerifyClassLoaderDexFiles(soa,
    405                             class_loader,
    406                             WellKnownClasses::dalvik_system_PathClassLoader,
    407                             expected_classpath);
    408 }
    409 
    410 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithEmptyContext) {
    411   std::unique_ptr<ClassLoaderContext> context =
    412       ClassLoaderContext::Create("");
    413   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
    414 
    415   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
    416 
    417   std::vector<const DexFile*> compilation_sources_raw =
    418       MakeNonOwningPointerVector(compilation_sources);
    419   jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
    420   ASSERT_TRUE(jclass_loader != nullptr);
    421 
    422   ScopedObjectAccess soa(Thread::Current());
    423 
    424   StackHandleScope<1> hs(soa.Self());
    425   Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
    426       soa.Decode<mirror::ClassLoader>(jclass_loader));
    427 
    428   // An empty context should create a single PathClassLoader with only the compilation sources.
    429   VerifyClassLoaderDexFiles(soa,
    430                             class_loader,
    431                             WellKnownClasses::dalvik_system_PathClassLoader,
    432                             compilation_sources_raw);
    433   ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
    434       soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
    435 }
    436 
    437 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
    438   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
    439 
    440   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
    441 
    442   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
    443 
    444   std::vector<const DexFile*> compilation_sources_raw =
    445       MakeNonOwningPointerVector(compilation_sources);
    446   jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
    447   ASSERT_TRUE(jclass_loader != nullptr);
    448 
    449   ScopedObjectAccess soa(Thread::Current());
    450 
    451   StackHandleScope<1> hs(soa.Self());
    452   Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
    453       soa.Decode<mirror::ClassLoader>(jclass_loader));
    454 
    455   // A shared library context should create a single PathClassLoader with only the compilation
    456   // sources.
    457   VerifyClassLoaderDexFiles(soa,
    458       class_loader,
    459       WellKnownClasses::dalvik_system_PathClassLoader,
    460       compilation_sources_raw);
    461   ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
    462   soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
    463 }
    464 
    465 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
    466   // Setup the context.
    467   std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");
    468   std::vector<std::unique_ptr<const DexFile>> classpath_dex_b = OpenTestDexFiles("ForClassLoaderB");
    469   std::vector<std::unique_ptr<const DexFile>> classpath_dex_c = OpenTestDexFiles("ForClassLoaderC");
    470   std::vector<std::unique_ptr<const DexFile>> classpath_dex_d = OpenTestDexFiles("ForClassLoaderD");
    471 
    472   std::string context_spec =
    473       "PCL[" + CreateClassPath(classpath_dex_a) + ":" + CreateClassPath(classpath_dex_b) + "];" +
    474       "DLC[" + CreateClassPath(classpath_dex_c) + "];" +
    475       "PCL[" + CreateClassPath(classpath_dex_d) + "]";
    476 
    477   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_spec);
    478   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
    479 
    480   // Setup the compilation sources.
    481   std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
    482   std::vector<const DexFile*> compilation_sources_raw =
    483       MakeNonOwningPointerVector(compilation_sources);
    484 
    485   // Create the class loader.
    486   jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
    487   ASSERT_TRUE(jclass_loader != nullptr);
    488 
    489   // Verify the class loader.
    490   ScopedObjectAccess soa(Thread::Current());
    491 
    492   StackHandleScope<3> hs(soa.Self());
    493   Handle<mirror::ClassLoader> class_loader_1 = hs.NewHandle(
    494       soa.Decode<mirror::ClassLoader>(jclass_loader));
    495 
    496   // Verify the first class loader
    497 
    498   // For the first class loader the class path dex files must come first and then the
    499   // compilation sources.
    500   std::vector<const DexFile*> class_loader_1_dex_files =
    501       MakeNonOwningPointerVector(classpath_dex_a);
    502   for (auto& dex : classpath_dex_b) {
    503     class_loader_1_dex_files.push_back(dex.get());
    504   }
    505   for (auto& dex : compilation_sources_raw) {
    506     class_loader_1_dex_files.push_back(dex);
    507   }
    508   VerifyClassLoaderDexFiles(soa,
    509                             class_loader_1,
    510                             WellKnownClasses::dalvik_system_PathClassLoader,
    511                             class_loader_1_dex_files);
    512 
    513   // Verify the second class loader
    514   Handle<mirror::ClassLoader> class_loader_2 = hs.NewHandle(class_loader_1->GetParent());
    515   std::vector<const DexFile*> class_loader_2_dex_files =
    516       MakeNonOwningPointerVector(classpath_dex_c);
    517   VerifyClassLoaderDexFiles(soa,
    518                             class_loader_2,
    519                             WellKnownClasses::dalvik_system_DelegateLastClassLoader,
    520                             class_loader_2_dex_files);
    521 
    522   // Verify the third class loader
    523   Handle<mirror::ClassLoader> class_loader_3 = hs.NewHandle(class_loader_2->GetParent());
    524   std::vector<const DexFile*> class_loader_3_dex_files =
    525       MakeNonOwningPointerVector(classpath_dex_d);
    526   VerifyClassLoaderDexFiles(soa,
    527                             class_loader_3,
    528                             WellKnownClasses::dalvik_system_PathClassLoader,
    529                             class_loader_3_dex_files);
    530   // The last class loader should have the BootClassLoader as a parent.
    531   ASSERT_TRUE(class_loader_3->GetParent()->GetClass() ==
    532       soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
    533 }
    534 
    535 
    536 TEST_F(ClassLoaderContextTest, RemoveSourceLocations) {
    537   std::unique_ptr<ClassLoaderContext> context =
    538       ClassLoaderContext::Create("PCL[a.dex]");
    539   dchecked_vector<std::string> classpath_dex;
    540   classpath_dex.push_back("a.dex");
    541   dchecked_vector<std::string> compilation_sources;
    542   compilation_sources.push_back("src.dex");
    543 
    544   // Nothing should be removed.
    545   ASSERT_FALSE(context->RemoveLocationsFromClassPaths(compilation_sources));
    546   VerifyClassLoaderPCL(context.get(), 0, "a.dex");
    547   // Classes should be removed.
    548   ASSERT_TRUE(context->RemoveLocationsFromClassPaths(classpath_dex));
    549   VerifyClassLoaderPCL(context.get(), 0, "");
    550 }
    551 
    552 TEST_F(ClassLoaderContextTest, EncodeInOatFile) {
    553   std::string dex1_name = GetTestDexFileName("Main");
    554   std::string dex2_name = GetTestDexFileName("MyClass");
    555   std::unique_ptr<ClassLoaderContext> context =
    556       ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
    557   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
    558 
    559   std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
    560   std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MyClass");
    561   std::string encoding = context->EncodeContextForOatFile("");
    562   std::string expected_encoding = "PCL[" + CreateClassPathWithChecksums(dex1) + ":" +
    563       CreateClassPathWithChecksums(dex2) + "]";
    564   ASSERT_EQ(expected_encoding, context->EncodeContextForOatFile(""));
    565 }
    566 
    567 TEST_F(ClassLoaderContextTest, EncodeForDex2oat) {
    568   std::string dex1_name = GetTestDexFileName("Main");
    569   std::string dex2_name = GetTestDexFileName("MultiDex");
    570   std::unique_ptr<ClassLoaderContext> context =
    571       ClassLoaderContext::Create("PCL[" + dex1_name + ":" + dex2_name + "]");
    572   ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
    573 
    574   std::vector<std::unique_ptr<const DexFile>> dex1 = OpenTestDexFiles("Main");
    575   std::vector<std::unique_ptr<const DexFile>> dex2 = OpenTestDexFiles("MultiDex");
    576   std::string encoding = context->EncodeContextForDex2oat("");
    577   std::string expected_encoding = "PCL[" + dex1_name + ":" + dex2_name + "]";
    578   ASSERT_EQ(expected_encoding, context->EncodeContextForDex2oat(""));
    579 }
    580 
    581 // TODO(calin) add a test which creates the context for a class loader together with dex_elements.
    582 TEST_F(ClassLoaderContextTest, CreateContextForClassLoader) {
    583   // The chain is
    584   //    ClassLoaderA (PathClassLoader)
    585   //       ^
    586   //       |
    587   //    ClassLoaderB (DelegateLastClassLoader)
    588   //       ^
    589   //       |
    590   //    ClassLoaderC (PathClassLoader)
    591   //       ^
    592   //       |
    593   //    ClassLoaderD (DelegateLastClassLoader)
    594 
    595   jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
    596   jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
    597   jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
    598   jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
    599 
    600   std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
    601 
    602   VerifyContextForClassLoader(context.get());
    603   VerifyContextSize(context.get(), 4);
    604 
    605   VerifyClassLoaderDLCFromTestDex(context.get(), 0, "ForClassLoaderD");
    606   VerifyClassLoaderPCLFromTestDex(context.get(), 1, "ForClassLoaderC");
    607   VerifyClassLoaderDLCFromTestDex(context.get(), 2, "ForClassLoaderB");
    608   VerifyClassLoaderPCLFromTestDex(context.get(), 3, "ForClassLoaderA");
    609 }
    610 
    611 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatch) {
    612   std::string context_spec = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890]";
    613   std::unique_ptr<ClassLoaderContext> context = ParseContextWithChecksums(context_spec);
    614   // Pretend that we successfully open the dex files to pass the DCHECKS.
    615   // (as it's much easier to test all the corner cases without relying on actual dex files).
    616   PretendContextOpenedDexFiles(context.get());
    617 
    618   VerifyContextSize(context.get(), 2);
    619   VerifyClassLoaderPCL(context.get(), 0, "a.dex:b.dex");
    620   VerifyClassLoaderDLC(context.get(), 1, "c.dex");
    621 
    622   ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_spec));
    623 
    624   std::string wrong_class_loader_type = "PCL[a.dex*123:b.dex*456];PCL[c.dex*890]";
    625   ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_type));
    626 
    627   std::string wrong_class_loader_order = "DLC[c.dex*890];PCL[a.dex*123:b.dex*456]";
    628   ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_class_loader_order));
    629 
    630   std::string wrong_classpath_order = "PCL[b.dex*456:a.dex*123];DLC[c.dex*890]";
    631   ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_classpath_order));
    632 
    633   std::string wrong_checksum = "PCL[a.dex*999:b.dex*456];DLC[c.dex*890]";
    634   ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_checksum));
    635 
    636   std::string wrong_extra_class_loader = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890];PCL[d.dex*321]";
    637   ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_class_loader));
    638 
    639   std::string wrong_extra_classpath = "PCL[a.dex*123:b.dex*456];DLC[c.dex*890:d.dex*321]";
    640   ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_extra_classpath));
    641 
    642   std::string wrong_spec = "PCL[a.dex*999:b.dex*456];DLC[";
    643   ASSERT_FALSE(context->VerifyClassLoaderContextMatch(wrong_spec));
    644 }
    645 
    646 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncoding) {
    647   jobject class_loader_a = LoadDexInPathClassLoader("ForClassLoaderA", nullptr);
    648   jobject class_loader_b = LoadDexInDelegateLastClassLoader("ForClassLoaderB", class_loader_a);
    649   jobject class_loader_c = LoadDexInPathClassLoader("ForClassLoaderC", class_loader_b);
    650   jobject class_loader_d = LoadDexInDelegateLastClassLoader("ForClassLoaderD", class_loader_c);
    651 
    652   std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader_d);
    653 
    654   std::string context_with_no_base_dir = context->EncodeContextForOatFile("");
    655   ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_no_base_dir));
    656 
    657   std::string dex_location = GetTestDexFileName("ForClassLoaderA");
    658   size_t pos = dex_location.rfind('/');
    659   ASSERT_NE(std::string::npos, pos);
    660   std::string parent = dex_location.substr(0, pos);
    661 
    662   std::string context_with_base_dir = context->EncodeContextForOatFile(parent);
    663   ASSERT_NE(context_with_base_dir, context_with_no_base_dir);
    664   ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context_with_base_dir));
    665 }
    666 
    667 TEST_F(ClassLoaderContextTest, VerifyClassLoaderContextMatchAfterEncodingMultidex) {
    668   jobject class_loader = LoadDexInPathClassLoader("MultiDex", nullptr);
    669 
    670   std::unique_ptr<ClassLoaderContext> context = CreateContextForClassLoader(class_loader);
    671 
    672   ASSERT_TRUE(context->VerifyClassLoaderContextMatch(context->EncodeContextForOatFile("")));
    673 }
    674 
    675 }  // namespace art
    676