Be prepared to handle empty class loader contexts

When executing run-tests we can hit an empty class loader contexts if the
compilation sources are passed with "-cp" and later removed from the
context.

Be prepared for such case and assume a PathClassLoader context.

Bug: 63977059
Test: ./art/test/run-test --host --optimizing --dev
      test-art-host

(cherry picked from commit 1a509c8effc938ba3da0f90ad83abb124b296386)

Change-Id: I2db637a1fc83beb760e1724edd6138b0614aa19b
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index eab3b86..ff440d7 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -145,6 +145,10 @@
 // ClasspathElem is the path of dex/jar/apk file.
 bool ClassLoaderContext::Parse(const std::string& spec, bool parse_checksums) {
   if (spec.empty()) {
+    // By default we load the dex files in a PathClassLoader.
+    // So an empty spec is equivalent to an empty PathClassLoader (this happens when running
+    // tests)
+    class_loader_chain_.push_back(ClassLoaderInfo(kPathClassLoader));
     return true;
   }
 
@@ -265,11 +269,15 @@
     return OatFile::kSpecialSharedLibrary;
   }
 
-  if (class_loader_chain_.empty()) {
-    return "";
-  }
-
   std::ostringstream out;
+  if (class_loader_chain_.empty()) {
+    // We can get in this situation if the context was created with a class path containing the
+    // source dex files which were later removed (happens during run-tests).
+    out << GetClassLoaderTypeName(kPathClassLoader)
+        << kClassLoaderOpeningMark
+        << kClassLoaderClosingMark;
+    return out.str();
+  }
 
   for (size_t i = 0; i < class_loader_chain_.size(); i++) {
     const ClassLoaderInfo& info = class_loader_chain_[i];
diff --git a/runtime/class_loader_context_test.cc b/runtime/class_loader_context_test.cc
index a87552d..10b80e0 100644
--- a/runtime/class_loader_context_test.cc
+++ b/runtime/class_loader_context_test.cc
@@ -162,6 +162,19 @@
   }
 };
 
+TEST_F(ClassLoaderContextTest, ParseValidEmptyContext) {
+  std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("");
+  // An empty context should create a single empty PathClassLoader.
+  VerifyContextSize(context.get(), 1);
+  VerifyClassLoaderPCL(context.get(), 0, "");
+}
+
+TEST_F(ClassLoaderContextTest, ParseValidSharedLibraryContext) {
+  std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
+  // An shared library context should have no class loader in the chain.
+  VerifyContextSize(context.get(), 0);
+}
+
 TEST_F(ClassLoaderContextTest, ParseValidContextPCL) {
   std::unique_ptr<ClassLoaderContext> context =
       ClassLoaderContext::Create("PCL[a.dex]");
@@ -313,6 +326,34 @@
       soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
 }
 
+TEST_F(ClassLoaderContextTest, CreateClassLoaderWithSharedLibraryContext) {
+  std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create("&");
+
+  ASSERT_TRUE(context->OpenDexFiles(InstructionSet::kArm, ""));
+
+  std::vector<std::unique_ptr<const DexFile>> compilation_sources = OpenTestDexFiles("MultiDex");
+
+  std::vector<const DexFile*> compilation_sources_raw =
+      MakeNonOwningPointerVector(compilation_sources);
+  jobject jclass_loader = context->CreateClassLoader(compilation_sources_raw);
+  ASSERT_TRUE(jclass_loader != nullptr);
+
+  ScopedObjectAccess soa(Thread::Current());
+
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
+      soa.Decode<mirror::ClassLoader>(jclass_loader));
+
+  // A shared library context should create a single PathClassLoader with only the compilation
+  // sources.
+  VerifyClassLoaderDexFiles(soa,
+      class_loader,
+      WellKnownClasses::dalvik_system_PathClassLoader,
+      compilation_sources_raw);
+  ASSERT_TRUE(class_loader->GetParent()->GetClass() ==
+  soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
+}
+
 TEST_F(ClassLoaderContextTest, CreateClassLoaderWithComplexChain) {
   // Setup the context.
   std::vector<std::unique_ptr<const DexFile>> classpath_dex_a = OpenTestDexFiles("ForClassLoaderA");