Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2014 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 "oat_file_assistant.h"
     18 
     19 #include <sys/param.h>
     20 
     21 #include <string>
     22 #include <vector>
     23 #include <fcntl.h>
     24 
     25 #include <gtest/gtest.h>
     26 
     27 #include "android-base/strings.h"
     28 
     29 #include "art_field-inl.h"
     30 #include "base/os.h"
     31 #include "base/utils.h"
     32 #include "class_linker-inl.h"
     33 #include "class_loader_context.h"
     34 #include "common_runtime_test.h"
     35 #include "dexopt_test.h"
     36 #include "hidden_api.h"
     37 #include "oat_file.h"
     38 #include "oat_file_manager.h"
     39 #include "scoped_thread_state_change-inl.h"
     40 #include "thread-current-inl.h"
     41 
     42 namespace art {
     43 
     44 class OatFileAssistantTest : public DexoptTest {
     45  public:
     46   void VerifyOptimizationStatus(const std::string& file,
     47                                 const std::string& expected_filter,
     48                                 const std::string& expected_reason) {
     49     std::string compilation_filter;
     50     std::string compilation_reason;
     51     OatFileAssistant::GetOptimizationStatus(
     52         file, kRuntimeISA, &compilation_filter, &compilation_reason);
     53 
     54     ASSERT_EQ(expected_filter, compilation_filter);
     55     ASSERT_EQ(expected_reason, compilation_reason);
     56   }
     57 
     58   void VerifyOptimizationStatus(const std::string& file,
     59                                 CompilerFilter::Filter expected_filter,
     60                                 const std::string& expected_reason) {
     61       VerifyOptimizationStatus(
     62           file, CompilerFilter::NameOfFilter(expected_filter), expected_reason);
     63   }
     64   void InsertNewBootClasspathEntry() {
     65     std::string extra_dex_filename = GetMultiDexSrc1();
     66     Runtime* runtime = Runtime::Current();
     67     runtime->boot_class_path_.push_back(extra_dex_filename);
     68     if (!runtime->boot_class_path_locations_.empty()) {
     69       runtime->boot_class_path_locations_.push_back(extra_dex_filename);
     70     }
     71   }
     72 };
     73 
     74 class ScopedNonWritable {
     75  public:
     76   explicit ScopedNonWritable(const std::string& dex_location) {
     77     is_valid_ = false;
     78     size_t pos = dex_location.rfind('/');
     79     if (pos != std::string::npos) {
     80       is_valid_ = true;
     81       dex_parent_ = dex_location.substr(0, pos);
     82       if (chmod(dex_parent_.c_str(), 0555) != 0)  {
     83         PLOG(ERROR) << "Could not change permissions on " << dex_parent_;
     84       }
     85     }
     86   }
     87 
     88   bool IsSuccessful() { return is_valid_ && (access(dex_parent_.c_str(), W_OK) != 0); }
     89 
     90   ~ScopedNonWritable() {
     91     if (is_valid_) {
     92       if (chmod(dex_parent_.c_str(), 0777) != 0) {
     93         PLOG(ERROR) << "Could not restore permissions on " << dex_parent_;
     94       }
     95     }
     96   }
     97 
     98  private:
     99   std::string dex_parent_;
    100   bool is_valid_;
    101 };
    102 
    103 static bool IsExecutedAsRoot() {
    104   return geteuid() == 0;
    105 }
    106 
    107 // Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
    108 // encoded dex locations.
    109 // Expect: The oat file status is kNoDexOptNeeded.
    110 TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
    111   std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
    112   std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
    113 
    114   // Create the dex file
    115   Copy(GetMultiDexSrc1(), dex_location);
    116 
    117   // Create the oat file with relative encoded dex location.
    118   std::vector<std::string> args = {
    119     "--dex-file=" + dex_location,
    120     "--dex-location=" + std::string("RelativeEncodedDexLocation.jar"),
    121     "--oat-file=" + odex_location,
    122     "--compiler-filter=speed"
    123   };
    124 
    125   std::string error_msg;
    126   ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
    127 
    128   // Verify we can load both dex files.
    129   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
    130 
    131   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
    132   ASSERT_TRUE(oat_file.get() != nullptr);
    133   EXPECT_TRUE(oat_file->IsExecutable());
    134   std::vector<std::unique_ptr<const DexFile>> dex_files;
    135   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
    136   EXPECT_EQ(2u, dex_files.size());
    137 }
    138 
    139 TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
    140   std::string dex_location = GetScratchDir() + "/TestDex.jar";
    141   std::string odex_location = GetOdexDir() + "/TestDex.odex";
    142   std::string context_location = GetScratchDir() + "/ContextDex.jar";
    143   Copy(GetDexSrc1(), dex_location);
    144   Copy(GetDexSrc2(), context_location);
    145 
    146   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    147 
    148   std::string context_str = "PCL[" + context_location + "]";
    149   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
    150   ASSERT_TRUE(context != nullptr);
    151   ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
    152 
    153   std::string error_msg;
    154   std::vector<std::string> args;
    155   args.push_back("--dex-file=" + dex_location);
    156   args.push_back("--oat-file=" + odex_location);
    157   args.push_back("--class-loader-context=" + context_str);
    158   ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
    159 
    160   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
    161   EXPECT_NE(nullptr, oat_file.get());
    162   EXPECT_EQ(context->EncodeContextForOatFile(""),
    163             oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
    164 }
    165 
    166 TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
    167   std::string dex_location = GetScratchDir() + "/TestDex.jar";
    168   std::string odex_location = GetOdexDir() + "/TestDex.odex";
    169   std::string context_location = GetScratchDir() + "/ContextDex.jar";
    170   Copy(GetDexSrc1(), dex_location);
    171   Copy(GetDexSrc2(), context_location);
    172 
    173   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    174 
    175   std::string context_str = "PCL[" + context_location + "]";
    176   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
    177   ASSERT_TRUE(context != nullptr);
    178   ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
    179 
    180   std::string error_msg;
    181   std::vector<std::string> args;
    182   args.push_back("--dex-file=" + dex_location);
    183   args.push_back("--oat-file=" + odex_location);
    184   args.push_back("--class-loader-context=" + context_str);
    185   ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
    186 
    187   // A relative context simulates a dependent split context.
    188   std::unique_ptr<ClassLoaderContext> relative_context =
    189       ClassLoaderContext::Create("PCL[ContextDex.jar]");
    190   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    191             oat_file_assistant.GetDexOptNeeded(
    192                 CompilerFilter::kDefaultCompilerFilter,
    193                 /* profile_changed= */ false,
    194                 /* downgrade= */ false,
    195                 relative_context.get()));
    196 }
    197 
    198 // Case: We have a DEX file, but no OAT file for it.
    199 // Expect: The status is kDex2OatNeeded.
    200 TEST_F(OatFileAssistantTest, DexNoOat) {
    201   std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
    202   Copy(GetDexSrc1(), dex_location);
    203 
    204   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    205 
    206   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    207       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    208   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    209       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    210   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    211       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
    212   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    213       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    214 
    215   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    216   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    217   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    218   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    219 
    220   VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
    221 }
    222 
    223 // Case: We have no DEX file and no OAT file.
    224 // Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
    225 TEST_F(OatFileAssistantTest, NoDexNoOat) {
    226   std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
    227 
    228   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
    229 
    230   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    231       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    232   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
    233 
    234   // Trying to get the best oat file should fail, but not crash.
    235   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
    236   EXPECT_EQ(nullptr, oat_file.get());
    237 }
    238 
    239 // Case: We have a DEX file and an ODEX file, but no OAT file.
    240 // Expect: The status is kNoDexOptNeeded.
    241 TEST_F(OatFileAssistantTest, OdexUpToDate) {
    242   std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
    243   std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
    244   Copy(GetDexSrc1(), dex_location);
    245   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
    246 
    247   // Force the use of oat location by making the dex parent not writable.
    248   OatFileAssistant oat_file_assistant(
    249       dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false);
    250 
    251   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    252             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    253   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    254             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    255   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    256             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    257   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
    258             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
    259 
    260   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    261   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    262   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    263   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    264 
    265   VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
    266 }
    267 
    268 // Case: We have an ODEX file compiled against partial boot image.
    269 // Expect: The status is kNoDexOptNeeded.
    270 TEST_F(OatFileAssistantTest, OdexUpToDatePartialBootImage) {
    271   std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
    272   std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
    273   Copy(GetDexSrc1(), dex_location);
    274   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
    275 
    276   // Insert an extra dex file to the boot class path.
    277   InsertNewBootClasspathEntry();
    278 
    279   // Force the use of oat location by making the dex parent not writable.
    280   OatFileAssistant oat_file_assistant(
    281       dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false);
    282 
    283   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    284             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    285   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    286             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    287   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    288             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    289   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
    290             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
    291 
    292   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    293   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    294   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    295   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    296 
    297   VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
    298 }
    299 
    300 // Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
    301 // file via a symlink.
    302 // Expect: The status is kNoDexOptNeeded.
    303 TEST_F(OatFileAssistantTest, OdexUpToDateSymLink) {
    304   std::string scratch_dir = GetScratchDir();
    305   std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
    306   std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
    307 
    308   Copy(GetDexSrc1(), dex_location);
    309   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
    310 
    311   // Now replace the dex location with a symlink.
    312   std::string link = scratch_dir + "/link";
    313   ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str()));
    314   dex_location = link + "/OdexUpToDate.jar";
    315 
    316   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    317 
    318   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    319       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    320   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    321       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    322   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    323       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    324   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
    325       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
    326 
    327   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    328   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    329   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    330   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    331 }
    332 
    333 // Case: We have a DEX file and up-to-date OAT file for it.
    334 // Expect: The status is kNoDexOptNeeded.
    335 TEST_F(OatFileAssistantTest, OatUpToDate) {
    336   if (IsExecutedAsRoot()) {
    337     // We cannot simulate non writable locations when executed as root: b/38000545.
    338     LOG(ERROR) << "Test skipped because it's running as root";
    339     return;
    340   }
    341 
    342   std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
    343   Copy(GetDexSrc1(), dex_location);
    344   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
    345 
    346   // Force the use of oat location by making the dex parent not writable.
    347   ScopedNonWritable scoped_non_writable(dex_location);
    348   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
    349 
    350   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    351 
    352   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    353       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    354   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    355       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    356   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    357       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    358   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
    359       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
    360 
    361   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    362   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    363   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
    364   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    365 
    366   VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "unknown");
    367 }
    368 
    369 // Case: Passing valid file descriptors of updated odex/vdex files along with the dex file.
    370 // Expect: The status is kNoDexOptNeeded.
    371 TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) {
    372   std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
    373   std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
    374   std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
    375 
    376   Copy(GetDexSrc1(), dex_location);
    377   GenerateOatForTest(dex_location.c_str(),
    378                      odex_location.c_str(),
    379                      CompilerFilter::kSpeed,
    380                      /* with_alternate_image= */ false);
    381 
    382   android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY | O_CLOEXEC));
    383   android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY | O_CLOEXEC));
    384   android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
    385 
    386   OatFileAssistant oat_file_assistant(dex_location.c_str(),
    387                                       kRuntimeISA,
    388                                       false,
    389                                       false,
    390                                       vdex_fd.get(),
    391                                       odex_fd.get(),
    392                                       zip_fd.get());
    393   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    394       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    395   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    396       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    397   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    398       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    399   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
    400       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
    401 
    402   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    403   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    404   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    405   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    406 }
    407 
    408 // Case: Passing invalid odex fd and valid vdex and zip fds.
    409 // Expect: The status should be kDex2OatForBootImage.
    410 TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
    411   std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
    412   std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
    413   std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
    414 
    415   Copy(GetDexSrc1(), dex_location);
    416   GenerateOatForTest(dex_location.c_str(),
    417                      odex_location.c_str(),
    418                      CompilerFilter::kSpeed,
    419                      /* with_alternate_image= */ false);
    420 
    421   android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY | O_CLOEXEC));
    422   android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
    423 
    424   OatFileAssistant oat_file_assistant(dex_location.c_str(),
    425                                       kRuntimeISA,
    426                                       false,
    427                                       false,
    428                                       vdex_fd.get(),
    429                                       /* oat_fd= */ -1,
    430                                       zip_fd.get());
    431   EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
    432       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    433   EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
    434       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
    435 
    436   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    437   EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
    438   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    439   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    440 }
    441 
    442 // Case: Passing invalid vdex fd and valid odex and zip fds.
    443 // Expect: The status should be kDex2OatFromScratch.
    444 TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
    445   std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
    446   std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
    447 
    448   Copy(GetDexSrc1(), dex_location);
    449   GenerateOatForTest(dex_location.c_str(),
    450                      odex_location.c_str(),
    451                      CompilerFilter::kSpeed,
    452                      /* with_alternate_image= */ false);
    453 
    454   android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY | O_CLOEXEC));
    455   android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
    456 
    457   OatFileAssistant oat_file_assistant(dex_location.c_str(),
    458                                       kRuntimeISA,
    459                                       false,
    460                                       false,
    461                                       /* vdex_fd= */ -1,
    462                                       odex_fd.get(),
    463                                       zip_fd.get());
    464 
    465   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    466       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    467   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    468   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    469   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    470   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    471 }
    472 
    473 // Case: Passing invalid vdex and odex fd with valid zip fd.
    474 // Expect: The status is kDex2oatFromScratch.
    475 TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
    476   std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
    477 
    478   Copy(GetDexSrc1(), dex_location);
    479 
    480   android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
    481   OatFileAssistant oat_file_assistant(dex_location.c_str(),
    482                                       kRuntimeISA,
    483                                       false,
    484                                       false,
    485                                       /* vdex_fd= */ -1,
    486                                       /* oat_fd= */ -1,
    487                                       zip_fd);
    488   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    489       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    490   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    491   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    492 }
    493 
    494 // Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
    495 // ODEX file.
    496 TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
    497   std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
    498   std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
    499 
    500   Copy(GetDexSrc1(), dex_location);
    501 
    502   // Generating and deleting the oat file should have the side effect of
    503   // creating an up-to-date vdex file.
    504   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
    505   ASSERT_EQ(0, unlink(odex_location.c_str()));
    506 
    507   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    508 
    509   // Even though the vdex file is up to date, because we don't have the oat
    510   // file, we can't know that the vdex depends on the boot image and is up to
    511   // date with respect to the boot image. Instead we must assume the vdex file
    512   // depends on the boot image and is out of date with respect to the boot
    513   // image.
    514   EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
    515       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    516 
    517   // Make sure we don't crash in this case when we dump the status. We don't
    518   // care what the actual dumped value is.
    519   oat_file_assistant.GetStatusDump();
    520 
    521   VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
    522 }
    523 
    524 // Case: We have a DEX file and empty VDEX and ODEX files.
    525 TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
    526   std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
    527   std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
    528   std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
    529 
    530   Copy(GetDexSrc1(), dex_location);
    531   ScratchFile vdex_file(vdex_location.c_str());
    532   ScratchFile odex_file(odex_location.c_str());
    533 
    534   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    535   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    536       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    537 }
    538 
    539 // Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
    540 // file.
    541 TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
    542   if (IsExecutedAsRoot()) {
    543     // We cannot simulate non writable locations when executed as root: b/38000545.
    544     LOG(ERROR) << "Test skipped because it's running as root";
    545     return;
    546   }
    547 
    548   std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
    549   std::string oat_location;
    550   std::string error_msg;
    551   ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
    552         dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
    553 
    554   Copy(GetDexSrc1(), dex_location);
    555   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
    556   ASSERT_EQ(0, unlink(oat_location.c_str()));
    557 
    558   ScopedNonWritable scoped_non_writable(dex_location);
    559   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
    560   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    561 
    562   // Even though the vdex file is up to date, because we don't have the oat
    563   // file, we can't know that the vdex depends on the boot image and is up to
    564   // date with respect to the boot image. Instead we must assume the vdex file
    565   // depends on the boot image and is out of date with respect to the boot
    566   // image.
    567   EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
    568       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    569 }
    570 
    571 // Case: We have a DEX file and speed-profile OAT file for it.
    572 // Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
    573 // kDex2Oat if the profile has changed.
    574 TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
    575   if (IsExecutedAsRoot()) {
    576     // We cannot simulate non writable locations when executed as root: b/38000545.
    577     LOG(ERROR) << "Test skipped because it's running as root";
    578     return;
    579   }
    580 
    581   std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
    582   Copy(GetDexSrc1(), dex_location);
    583   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
    584 
    585   ScopedNonWritable scoped_non_writable(dex_location);
    586   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
    587 
    588   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    589 
    590   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    591       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
    592   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    593       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
    594   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
    595       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
    596   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
    597       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
    598 
    599   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    600   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    601   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
    602   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    603 }
    604 
    605 // Case: We have a MultiDEX file and up-to-date OAT file for it.
    606 // Expect: The status is kNoDexOptNeeded and we load all dex files.
    607 TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
    608   if (IsExecutedAsRoot()) {
    609     // We cannot simulate non writable locations when executed as root: b/38000545.
    610     LOG(ERROR) << "Test skipped because it's running as root";
    611     return;
    612   }
    613 
    614   std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
    615   Copy(GetMultiDexSrc1(), dex_location);
    616   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
    617 
    618   ScopedNonWritable scoped_non_writable(dex_location);
    619   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
    620 
    621   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
    622   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    623       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
    624   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    625 
    626   // Verify we can load both dex files.
    627   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
    628   ASSERT_TRUE(oat_file.get() != nullptr);
    629   EXPECT_TRUE(oat_file->IsExecutable());
    630   std::vector<std::unique_ptr<const DexFile>> dex_files;
    631   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
    632   EXPECT_EQ(2u, dex_files.size());
    633 }
    634 
    635 // Case: We have a MultiDEX file where the non-main multdex entry is out of date.
    636 // Expect: The status is kDex2OatNeeded.
    637 TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
    638   if (IsExecutedAsRoot()) {
    639     // We cannot simulate non writable locations when executed as root: b/38000545.
    640     LOG(ERROR) << "Test skipped because it's running as root";
    641     return;
    642   }
    643 
    644   std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
    645 
    646   // Compile code for GetMultiDexSrc1.
    647   Copy(GetMultiDexSrc1(), dex_location);
    648   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
    649 
    650   // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
    651   // is out of date.
    652   Copy(GetMultiDexSrc2(), dex_location);
    653 
    654   ScopedNonWritable scoped_non_writable(dex_location);
    655   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
    656 
    657   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
    658   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    659       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
    660   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    661 }
    662 
    663 // Case: We have a stripped MultiDEX file where the non-main multidex entry is
    664 // out of date with respect to the odex file.
    665 TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
    666   std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
    667   std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
    668 
    669   // Compile the oat from GetMultiDexSrc1.
    670   Copy(GetMultiDexSrc1(), dex_location);
    671   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
    672 
    673   // Compile the odex from GetMultiDexSrc2, which has a different non-main
    674   // dex checksum.
    675   Copy(GetMultiDexSrc2(), dex_location);
    676   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
    677 
    678   // Strip the dex file.
    679   Copy(GetStrippedDexSrc1(), dex_location);
    680 
    681   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable=*/false);
    682 
    683   // Because the dex file is stripped, the odex file is considered the source
    684   // of truth for the dex checksums. The oat file should be considered
    685   // unusable.
    686   std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
    687   ASSERT_TRUE(best_file.get() != nullptr);
    688   EXPECT_EQ(best_file->GetLocation(), odex_location);
    689   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
    690   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    691   EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
    692 }
    693 
    694 // Case: We have a DEX file and an OAT file out of date with respect to the
    695 // dex checksum.
    696 TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
    697   if (IsExecutedAsRoot()) {
    698     // We cannot simulate non writable locations when executed as root: b/38000545.
    699     LOG(ERROR) << "Test skipped because it's running as root";
    700     return;
    701   }
    702 
    703   std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
    704 
    705   // We create a dex, generate an oat for it, then overwrite the dex with a
    706   // different dex to make the oat out of date.
    707   Copy(GetDexSrc1(), dex_location);
    708   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
    709   Copy(GetDexSrc2(), dex_location);
    710 
    711   ScopedNonWritable scoped_non_writable(dex_location);
    712   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
    713 
    714   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    715   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    716       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    717   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    718       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    719 
    720   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    721   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    722   EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
    723   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    724 }
    725 
    726 // Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
    727 // to the dex checksum, but no ODEX file.
    728 TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
    729   std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
    730   std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
    731 
    732   Copy(GetDexSrc1(), dex_location);
    733   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
    734   ASSERT_EQ(0, unlink(odex_location.c_str()));
    735   Copy(GetDexSrc2(), dex_location);
    736 
    737   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    738 
    739   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    740       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    741 }
    742 
    743 // Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
    744 // is out of date and there is no corresponding ODEX file.
    745 TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
    746   std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
    747   std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
    748 
    749   Copy(GetMultiDexSrc1(), dex_location);
    750   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
    751   ASSERT_EQ(0, unlink(odex_location.c_str()));
    752   Copy(GetMultiDexSrc2(), dex_location);
    753 
    754   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    755 
    756   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
    757       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    758 }
    759 
    760 // Case: We have a DEX file and an OAT file out of date with respect to the
    761 // boot image.
    762 TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
    763   if (IsExecutedAsRoot()) {
    764     // We cannot simulate non writable locations when executed as root: b/38000545.
    765     LOG(ERROR) << "Test skipped because it's running as root";
    766     return;
    767   }
    768 
    769   std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
    770 
    771   Copy(GetDexSrc1(), dex_location);
    772   GenerateOatForTest(dex_location.c_str(),
    773                      CompilerFilter::kSpeed,
    774                      /* with_alternate_image= */ true);
    775 
    776   ScopedNonWritable scoped_non_writable(dex_location);
    777   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
    778 
    779   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    780   EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
    781       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    782   EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
    783       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    784   EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
    785       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    786 
    787   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    788   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    789   EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
    790   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    791 }
    792 
    793 // Case: We have a DEX file and a verify-at-runtime OAT file out of date with
    794 // respect to the boot image.
    795 // It shouldn't matter that the OAT file is out of date, because it is
    796 // verify-at-runtime.
    797 TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
    798   if (IsExecutedAsRoot()) {
    799     // We cannot simulate non writable locations when executed as root: b/38000545.
    800     LOG(ERROR) << "Test skipped because it's running as root";
    801     return;
    802   }
    803 
    804   std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
    805 
    806   Copy(GetDexSrc1(), dex_location);
    807   GenerateOatForTest(dex_location.c_str(),
    808                      CompilerFilter::kExtract,
    809                      /* with_alternate_image= */ true);
    810 
    811   ScopedNonWritable scoped_non_writable(dex_location);
    812   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
    813 
    814   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    815   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    816       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    817   EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
    818       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    819 
    820   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    821   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    822   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
    823   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    824 }
    825 
    826 // Case: We have a DEX file and an ODEX file, but no OAT file.
    827 TEST_F(OatFileAssistantTest, DexOdexNoOat) {
    828   std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
    829   std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
    830 
    831   // Create the dex and odex files
    832   Copy(GetDexSrc1(), dex_location);
    833   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
    834 
    835   // Verify the status.
    836   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    837 
    838   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    839       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    840   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    841       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    842 
    843   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    844   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    845   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    846   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    847 
    848   // We should still be able to get the non-executable odex file to run from.
    849   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
    850   ASSERT_TRUE(oat_file.get() != nullptr);
    851 }
    852 
    853 // Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
    854 TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
    855   std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
    856   std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
    857 
    858   // Create the dex and odex files
    859   Copy(GetDexSrc1(), dex_location);
    860   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
    861 
    862   // Strip the dex file
    863   Copy(GetStrippedDexSrc1(), dex_location);
    864 
    865   // Verify the status.
    866   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
    867 
    868   EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
    869       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    870 
    871   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    872   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    873   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    874   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
    875 
    876   // Verify we can load the dex files from it.
    877   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
    878   ASSERT_TRUE(oat_file.get() != nullptr);
    879   EXPECT_TRUE(oat_file->IsExecutable());
    880   std::vector<std::unique_ptr<const DexFile>> dex_files;
    881   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
    882   EXPECT_EQ(1u, dex_files.size());
    883 }
    884 
    885 // Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
    886 TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
    887   std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
    888   std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
    889 
    890   // Create the oat file from a different dex file so it looks out of date.
    891   Copy(GetDexSrc2(), dex_location);
    892   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
    893 
    894   // Create the odex file
    895   Copy(GetDexSrc1(), dex_location);
    896   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
    897 
    898   // Strip the dex file.
    899   Copy(GetStrippedDexSrc1(), dex_location);
    900 
    901   // Verify the status.
    902   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
    903 
    904   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    905       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    906   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    907       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    908   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,  // Compiling from the .vdex file
    909       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
    910 
    911   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    912   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    913   EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
    914   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
    915 
    916   // Verify we can load the dex files from it.
    917   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
    918   ASSERT_TRUE(oat_file.get() != nullptr);
    919   EXPECT_TRUE(oat_file->IsExecutable());
    920   std::vector<std::unique_ptr<const DexFile>> dex_files;
    921   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
    922   EXPECT_EQ(1u, dex_files.size());
    923 }
    924 
    925 // Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
    926 // OAT file. Expect: The status is kNoDexOptNeeded.
    927 TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
    928   std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
    929 
    930   Copy(GetStrippedDexSrc1(), dex_location);
    931 
    932   // Verify the status.
    933   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
    934 
    935   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    936       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    937   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    938       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
    939   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    940       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
    941 
    942   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    943   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    944   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    945   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
    946 
    947   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    948       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    949 
    950   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    951   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
    952   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
    953   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
    954 }
    955 
    956 // Case: We have a DEX file, an ODEX file and an OAT file.
    957 // Expect: It shouldn't crash. We should load the odex file executable.
    958 TEST_F(OatFileAssistantTest, OdexOatOverlap) {
    959   std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
    960   std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
    961 
    962   // Create the dex, the odex and the oat files.
    963   Copy(GetDexSrc1(), dex_location);
    964   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
    965   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
    966 
    967   // Verify things don't go bad.
    968   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
    969 
    970   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
    971             oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
    972 
    973   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
    974   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
    975   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
    976   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
    977 
    978   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
    979   ASSERT_TRUE(oat_file.get() != nullptr);
    980 
    981   EXPECT_TRUE(oat_file->IsExecutable());
    982   std::vector<std::unique_ptr<const DexFile>> dex_files;
    983   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
    984   EXPECT_EQ(1u, dex_files.size());
    985 }
    986 
    987 // Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
    988 // Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
    989 TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
    990   std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
    991   std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
    992 
    993   // Create the dex and odex files
    994   Copy(GetDexSrc1(), dex_location);
    995   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
    996 
    997   // Verify the status.
    998   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
    999 
   1000   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
   1001       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
   1002   EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
   1003       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
   1004 
   1005   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   1006   EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
   1007   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
   1008   EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
   1009 }
   1010 
   1011 // Case: We have a DEX file and up-to-date OAT file for it.
   1012 // Expect: We should load an executable dex file.
   1013 TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
   1014   if (IsExecutedAsRoot()) {
   1015     // We cannot simulate non writable locations when executed as root: b/38000545.
   1016     LOG(ERROR) << "Test skipped because it's running as root";
   1017     return;
   1018   }
   1019 
   1020   std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
   1021 
   1022   Copy(GetDexSrc1(), dex_location);
   1023   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
   1024 
   1025   ScopedNonWritable scoped_non_writable(dex_location);
   1026   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
   1027 
   1028   // Load the oat using an oat file assistant.
   1029   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
   1030 
   1031   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   1032   ASSERT_TRUE(oat_file.get() != nullptr);
   1033   EXPECT_TRUE(oat_file->IsExecutable());
   1034   std::vector<std::unique_ptr<const DexFile>> dex_files;
   1035   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
   1036   EXPECT_EQ(1u, dex_files.size());
   1037 }
   1038 
   1039 // Case: We have a DEX file and up-to-date quicken OAT file for it.
   1040 // Expect: We should still load the oat file as executable.
   1041 TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
   1042   if (IsExecutedAsRoot()) {
   1043     // We cannot simulate non writable locations when executed as root: b/38000545.
   1044     LOG(ERROR) << "Test skipped because it's running as root";
   1045     return;
   1046   }
   1047 
   1048   std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
   1049 
   1050   Copy(GetDexSrc1(), dex_location);
   1051   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
   1052 
   1053   ScopedNonWritable scoped_non_writable(dex_location);
   1054   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
   1055 
   1056   // Load the oat using an oat file assistant.
   1057   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
   1058 
   1059   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   1060   ASSERT_TRUE(oat_file.get() != nullptr);
   1061   EXPECT_TRUE(oat_file->IsExecutable());
   1062   std::vector<std::unique_ptr<const DexFile>> dex_files;
   1063   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
   1064   EXPECT_EQ(1u, dex_files.size());
   1065 }
   1066 
   1067 // Case: We have a DEX file and up-to-date OAT file for it.
   1068 // Expect: Loading non-executable should load the oat non-executable.
   1069 TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
   1070   if (IsExecutedAsRoot()) {
   1071     // We cannot simulate non writable locations when executed as root: b/38000545.
   1072     LOG(ERROR) << "Test skipped because it's running as root";
   1073     return;
   1074   }
   1075 
   1076   std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
   1077 
   1078   Copy(GetDexSrc1(), dex_location);
   1079 
   1080   ScopedNonWritable scoped_non_writable(dex_location);
   1081   ASSERT_TRUE(scoped_non_writable.IsSuccessful());
   1082 
   1083   GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
   1084 
   1085   // Load the oat using an oat file assistant.
   1086   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
   1087 
   1088   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   1089   ASSERT_TRUE(oat_file.get() != nullptr);
   1090   EXPECT_FALSE(oat_file->IsExecutable());
   1091   std::vector<std::unique_ptr<const DexFile>> dex_files;
   1092   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
   1093   EXPECT_EQ(1u, dex_files.size());
   1094 }
   1095 
   1096 // Turn an absolute path into a path relative to the current working
   1097 // directory.
   1098 static std::string MakePathRelative(const std::string& target) {
   1099   char buf[MAXPATHLEN];
   1100   std::string cwd = getcwd(buf, MAXPATHLEN);
   1101 
   1102   // Split the target and cwd paths into components.
   1103   std::vector<std::string> target_path;
   1104   std::vector<std::string> cwd_path;
   1105   Split(target, '/', &target_path);
   1106   Split(cwd, '/', &cwd_path);
   1107 
   1108   // Reverse the path components, so we can use pop_back().
   1109   std::reverse(target_path.begin(), target_path.end());
   1110   std::reverse(cwd_path.begin(), cwd_path.end());
   1111 
   1112   // Drop the common prefix of the paths. Because we reversed the path
   1113   // components, this becomes the common suffix of target_path and cwd_path.
   1114   while (!target_path.empty() && !cwd_path.empty()
   1115       && target_path.back() == cwd_path.back()) {
   1116     target_path.pop_back();
   1117     cwd_path.pop_back();
   1118   }
   1119 
   1120   // For each element of the remaining cwd_path, add '..' to the beginning
   1121   // of the target path. Because we reversed the path components, we add to
   1122   // the end of target_path.
   1123   for (unsigned int i = 0; i < cwd_path.size(); i++) {
   1124     target_path.push_back("..");
   1125   }
   1126 
   1127   // Reverse again to get the right path order, and join to get the result.
   1128   std::reverse(target_path.begin(), target_path.end());
   1129   return android::base::Join(target_path, '/');
   1130 }
   1131 
   1132 // Case: Non-absolute path to Dex location.
   1133 // Expect: Not sure, but it shouldn't crash.
   1134 TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
   1135   std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
   1136   Copy(GetDexSrc1(), abs_dex_location);
   1137 
   1138   std::string dex_location = MakePathRelative(abs_dex_location);
   1139   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
   1140 
   1141   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   1142   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
   1143       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
   1144   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   1145   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
   1146 }
   1147 
   1148 // Case: Very short, non-existent Dex location.
   1149 // Expect: kNoDexOptNeeded.
   1150 TEST_F(OatFileAssistantTest, ShortDexLocation) {
   1151   std::string dex_location = "/xx";
   1152 
   1153   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
   1154 
   1155   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   1156   EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
   1157       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
   1158   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   1159   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
   1160   EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
   1161 }
   1162 
   1163 // Case: Non-standard extension for dex file.
   1164 // Expect: The status is kDex2OatNeeded.
   1165 TEST_F(OatFileAssistantTest, LongDexExtension) {
   1166   std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
   1167   Copy(GetDexSrc1(), dex_location);
   1168 
   1169   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
   1170 
   1171   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
   1172       oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
   1173 
   1174   EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
   1175   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
   1176   EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
   1177 }
   1178 
   1179 // A task to generate a dex location. Used by the RaceToGenerate test.
   1180 class RaceGenerateTask : public Task {
   1181  public:
   1182   RaceGenerateTask(OatFileAssistantTest& test,
   1183                    const std::string& dex_location,
   1184                    const std::string& oat_location,
   1185                    Mutex* lock)
   1186       : test_(test),
   1187         dex_location_(dex_location),
   1188         oat_location_(oat_location),
   1189         lock_(lock),
   1190         loaded_oat_file_(nullptr)
   1191   {}
   1192 
   1193   void Run(Thread* self ATTRIBUTE_UNUSED) override {
   1194     // Load the dex files, and save a pointer to the loaded oat file, so that
   1195     // we can verify only one oat file was loaded for the dex location.
   1196     std::vector<std::unique_ptr<const DexFile>> dex_files;
   1197     std::vector<std::string> error_msgs;
   1198     const OatFile* oat_file = nullptr;
   1199     {
   1200       MutexLock mu(Thread::Current(), *lock_);
   1201       // Create the oat file.
   1202       std::vector<std::string> args;
   1203       args.push_back("--dex-file=" + dex_location_);
   1204       args.push_back("--oat-file=" + oat_location_);
   1205       std::string error_msg;
   1206       ASSERT_TRUE(test_.Dex2Oat(args, &error_msg)) << error_msg;
   1207     }
   1208 
   1209     dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
   1210         dex_location_.c_str(),
   1211         Runtime::Current()->GetSystemClassLoader(),
   1212         /*dex_elements=*/nullptr,
   1213         &oat_file,
   1214         &error_msgs);
   1215     CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
   1216     if (dex_files[0]->GetOatDexFile() != nullptr) {
   1217       loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
   1218     }
   1219     CHECK_EQ(loaded_oat_file_, oat_file);
   1220   }
   1221 
   1222   const OatFile* GetLoadedOatFile() const {
   1223     return loaded_oat_file_;
   1224   }
   1225 
   1226  private:
   1227   OatFileAssistantTest& test_;
   1228   std::string dex_location_;
   1229   std::string oat_location_;
   1230   Mutex* lock_;
   1231   const OatFile* loaded_oat_file_;
   1232 };
   1233 
   1234 // Test the case where dex2oat invocations race with multiple processes trying to
   1235 // load the oat file.
   1236 TEST_F(OatFileAssistantTest, RaceToGenerate) {
   1237   std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
   1238   std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
   1239 
   1240   // Start the runtime to initialize the system's class loader.
   1241   Thread::Current()->TransitionFromSuspendedToRunnable();
   1242   runtime_->Start();
   1243 
   1244   // We use the lib core dex file, because it's large, and hopefully should
   1245   // take a while to generate.
   1246   Copy(GetLibCoreDexFileNames()[0], dex_location);
   1247 
   1248   const size_t kNumThreads = 32;
   1249   Thread* self = Thread::Current();
   1250   ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
   1251   std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
   1252   Mutex lock("RaceToGenerate");
   1253   for (size_t i = 0; i < kNumThreads; i++) {
   1254     std::unique_ptr<RaceGenerateTask> task(
   1255         new RaceGenerateTask(*this, dex_location, oat_location, &lock));
   1256     thread_pool.AddTask(self, task.get());
   1257     tasks.push_back(std::move(task));
   1258   }
   1259   thread_pool.StartWorkers(self);
   1260   thread_pool.Wait(self, /* do_work= */ true, /* may_hold_locks= */ false);
   1261 
   1262   // Verify that tasks which got an oat file got a unique one.
   1263   std::set<const OatFile*> oat_files;
   1264   for (auto& task : tasks) {
   1265     const OatFile* oat_file = task->GetLoadedOatFile();
   1266     if (oat_file != nullptr) {
   1267       EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
   1268       oat_files.insert(oat_file);
   1269     }
   1270   }
   1271 }
   1272 
   1273 // Case: We have a DEX file and an ODEX file, and no OAT file,
   1274 // Expect: We should load the odex file executable.
   1275 TEST_F(DexoptTest, LoadDexOdexNoOat) {
   1276   std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
   1277   std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
   1278 
   1279   // Create the dex and odex files
   1280   Copy(GetDexSrc1(), dex_location);
   1281   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
   1282 
   1283   // Load the oat using an executable oat file assistant.
   1284   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
   1285 
   1286   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   1287   ASSERT_TRUE(oat_file.get() != nullptr);
   1288   EXPECT_TRUE(oat_file->IsExecutable());
   1289   std::vector<std::unique_ptr<const DexFile>> dex_files;
   1290   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
   1291   EXPECT_EQ(1u, dex_files.size());
   1292 }
   1293 
   1294 // Case: We have a MultiDEX file and an ODEX file, and no OAT file.
   1295 // Expect: We should load the odex file executable.
   1296 TEST_F(DexoptTest, LoadMultiDexOdexNoOat) {
   1297   std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
   1298   std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
   1299 
   1300   // Create the dex and odex files
   1301   Copy(GetMultiDexSrc1(), dex_location);
   1302   GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
   1303 
   1304   // Load the oat using an executable oat file assistant.
   1305   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
   1306 
   1307   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   1308   ASSERT_TRUE(oat_file.get() != nullptr);
   1309   EXPECT_TRUE(oat_file->IsExecutable());
   1310   std::vector<std::unique_ptr<const DexFile>> dex_files;
   1311   dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
   1312   EXPECT_EQ(2u, dex_files.size());
   1313 }
   1314 
   1315 TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
   1316   std::string error_msg;
   1317   std::string odex_file;
   1318 
   1319   EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
   1320         "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
   1321   EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
   1322 
   1323   EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
   1324         "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
   1325   EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
   1326 
   1327   EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
   1328         "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
   1329   EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
   1330         "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
   1331 }
   1332 
   1333 // Verify the dexopt status values from dalvik.system.DexFile
   1334 // match the OatFileAssistant::DexOptStatus values.
   1335 TEST_F(OatFileAssistantTest, DexOptStatusValues) {
   1336   std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
   1337     {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
   1338     {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
   1339     {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
   1340     {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
   1341   };
   1342 
   1343   ScopedObjectAccess soa(Thread::Current());
   1344   StackHandleScope<1> hs(soa.Self());
   1345   ClassLinker* linker = Runtime::Current()->GetClassLinker();
   1346   Handle<mirror::Class> dexfile(
   1347       hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
   1348   ASSERT_FALSE(dexfile == nullptr);
   1349   linker->EnsureInitialized(soa.Self(), dexfile, true, true);
   1350 
   1351   for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
   1352     ArtField* art_field = mirror::Class::FindStaticField(
   1353         soa.Self(), dexfile.Get(), field.second, "I");
   1354     ASSERT_FALSE(art_field == nullptr);
   1355     EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   1356     EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
   1357   }
   1358 }
   1359 
   1360 TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
   1361   std::string dex_location = GetScratchDir() + "/TestDex.jar";
   1362   std::string context_location = GetScratchDir() + "/ContextDex.jar";
   1363   Copy(GetDexSrc1(), dex_location);
   1364   Copy(GetDexSrc2(), context_location);
   1365 
   1366   OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
   1367 
   1368   std::string error_msg;
   1369   std::string context_str = "PCL[" + context_location + "]";
   1370   std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
   1371   ASSERT_TRUE(context != nullptr);
   1372   ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
   1373 
   1374   // Update the context by overriding the jar file.
   1375   Copy(GetMultiDexSrc2(), context_location);
   1376   std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
   1377   ASSERT_TRUE(updated_context != nullptr);
   1378   // DexOptNeeded should advise compilation from scratch.
   1379   EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
   1380             oat_file_assistant.GetDexOptNeeded(
   1381                   CompilerFilter::kDefaultCompilerFilter,
   1382                   /* profile_changed= */ false,
   1383                   /* downgrade= */ false,
   1384                   updated_context.get()));
   1385 }
   1386 
   1387 // Test that GetLocation of a dex file is the same whether the dex
   1388 // filed is backed by an oat file or not.
   1389 TEST_F(OatFileAssistantTest, GetDexLocation) {
   1390   std::string dex_location = GetScratchDir() + "/TestDex.jar";
   1391   std::string oat_location = GetOdexDir() + "/TestDex.odex";
   1392 
   1393   // Start the runtime to initialize the system's class loader.
   1394   Thread::Current()->TransitionFromSuspendedToRunnable();
   1395   runtime_->Start();
   1396 
   1397   Copy(GetDexSrc1(), dex_location);
   1398 
   1399   std::vector<std::unique_ptr<const DexFile>> dex_files;
   1400   std::vector<std::string> error_msgs;
   1401   const OatFile* oat_file = nullptr;
   1402 
   1403   dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
   1404       dex_location.c_str(),
   1405       Runtime::Current()->GetSystemClassLoader(),
   1406       /*dex_elements=*/nullptr,
   1407       &oat_file,
   1408       &error_msgs);
   1409   EXPECT_EQ(dex_files.size(), 1u);
   1410   EXPECT_EQ(oat_file, nullptr);
   1411   std::string stored_dex_location = dex_files[0]->GetLocation();
   1412   {
   1413     // Create the oat file.
   1414     std::vector<std::string> args;
   1415     args.push_back("--dex-file=" + dex_location);
   1416     args.push_back("--dex-location=TestDex.jar");
   1417     args.push_back("--oat-file=" + oat_location);
   1418     std::string error_msg;
   1419     ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
   1420   }
   1421   dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
   1422       dex_location.c_str(),
   1423       Runtime::Current()->GetSystemClassLoader(),
   1424       /*dex_elements=*/nullptr,
   1425       &oat_file,
   1426       &error_msgs);
   1427   EXPECT_EQ(dex_files.size(), 1u);
   1428   EXPECT_NE(oat_file, nullptr);
   1429   std::string oat_stored_dex_location = dex_files[0]->GetLocation();
   1430   EXPECT_EQ(oat_stored_dex_location, stored_dex_location);
   1431 }
   1432 
   1433 // Test that a dex file on the platform location gets the right hiddenapi domain,
   1434 // regardless of whether it has a backing oat file.
   1435 TEST_F(OatFileAssistantTest, SystemFrameworkDir) {
   1436   std::string filebase = "OatFileAssistantTestSystemFrameworkDir";
   1437   std::string dex_location = GetAndroidRoot() + "/framework/" + filebase + ".jar";
   1438   Copy(GetDexSrc1(), dex_location);
   1439 
   1440   std::string odex_dir = GetAndroidRoot() + "/framework/oat/";
   1441   mkdir(odex_dir.c_str(), 0700);
   1442   odex_dir = odex_dir + std::string(GetInstructionSetString(kRuntimeISA));
   1443   mkdir(odex_dir.c_str(), 0700);
   1444   std::string oat_location = odex_dir + "/" + filebase + ".odex";
   1445   // Clean up in case previous run crashed.
   1446   remove(oat_location.c_str());
   1447 
   1448   // Start the runtime to initialize the system's class loader.
   1449   Thread::Current()->TransitionFromSuspendedToRunnable();
   1450   runtime_->Start();
   1451 
   1452   std::vector<std::unique_ptr<const DexFile>> dex_files_first;
   1453   std::vector<std::unique_ptr<const DexFile>> dex_files_second;
   1454   std::vector<std::string> error_msgs;
   1455   const OatFile* oat_file = nullptr;
   1456 
   1457   dex_files_first = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
   1458       dex_location.c_str(),
   1459       Runtime::Current()->GetSystemClassLoader(),
   1460       /*dex_elements=*/nullptr,
   1461       &oat_file,
   1462       &error_msgs);
   1463   EXPECT_EQ(dex_files_first.size(), 1u);
   1464   EXPECT_EQ(oat_file, nullptr) << dex_location;
   1465   EXPECT_EQ(dex_files_first[0]->GetOatDexFile(), nullptr);
   1466 
   1467   // Register the dex file to get a domain.
   1468   {
   1469     ScopedObjectAccess soa(Thread::Current());
   1470     Runtime::Current()->GetClassLinker()->RegisterDexFile(
   1471         *dex_files_first[0],
   1472         soa.Decode<mirror::ClassLoader>(Runtime::Current()->GetSystemClassLoader()));
   1473   }
   1474   std::string stored_dex_location = dex_files_first[0]->GetLocation();
   1475   EXPECT_EQ(dex_files_first[0]->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
   1476   {
   1477     // Create the oat file.
   1478     std::vector<std::string> args;
   1479     args.push_back("--dex-file=" + dex_location);
   1480     args.push_back("--dex-location=" + filebase + ".jar");
   1481     args.push_back("--oat-file=" + oat_location);
   1482     std::string error_msg;
   1483     ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
   1484   }
   1485   dex_files_second = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
   1486       dex_location.c_str(),
   1487       Runtime::Current()->GetSystemClassLoader(),
   1488       /*dex_elements=*/nullptr,
   1489       &oat_file,
   1490       &error_msgs);
   1491   EXPECT_EQ(dex_files_second.size(), 1u);
   1492   EXPECT_NE(oat_file, nullptr);
   1493   EXPECT_NE(dex_files_second[0]->GetOatDexFile(), nullptr);
   1494   EXPECT_NE(dex_files_second[0]->GetOatDexFile()->GetOatFile(), nullptr);
   1495 
   1496   // Register the dex file to get a domain.
   1497   {
   1498     ScopedObjectAccess soa(Thread::Current());
   1499     Runtime::Current()->GetClassLinker()->RegisterDexFile(
   1500         *dex_files_second[0],
   1501         soa.Decode<mirror::ClassLoader>(Runtime::Current()->GetSystemClassLoader()));
   1502   }
   1503   std::string oat_stored_dex_location = dex_files_second[0]->GetLocation();
   1504   EXPECT_EQ(oat_stored_dex_location, stored_dex_location);
   1505   EXPECT_EQ(dex_files_second[0]->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
   1506   EXPECT_EQ(0, remove(oat_location.c_str()));
   1507 }
   1508 
   1509 // TODO: More Tests:
   1510 //  * Test class linker falls back to unquickened dex for DexNoOat
   1511 //  * Test class linker falls back to unquickened dex for MultiDexNoOat
   1512 //  * Test using secondary isa
   1513 //  * Test for status of oat while oat is being generated (how?)
   1514 //  * Test case where 32 and 64 bit boot class paths differ,
   1515 //      and we ask IsInBootClassPath for a class in exactly one of the 32 or
   1516 //      64 bit boot class paths.
   1517 //  * Test unexpected scenarios (?):
   1518 //    - Dex is stripped, don't have odex.
   1519 //    - Oat file corrupted after status check, before reload unexecutable
   1520 //    because it's unrelocated and no dex2oat
   1521 }  // namespace art
   1522