diff options
| -rw-r--r-- | runtime/oat_file_assistant.cc | 13 | ||||
| -rw-r--r-- | runtime/oat_file_assistant_test.cc | 55 | ||||
| -rw-r--r-- | runtime/runtime.h | 2 |
3 files changed, 61 insertions, 9 deletions
diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 8b81bb9bfc..80ac01f41a 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -563,8 +563,17 @@ const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums() { bool OatFileAssistant::ImageInfo::ValidateBootClassPathChecksums(const OatFile& oat_file) const { const char* oat_boot_class_path_checksums = oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey); - return oat_boot_class_path_checksums != nullptr && - oat_boot_class_path_checksums == boot_class_path_checksums; + if (oat_boot_class_path_checksums == nullptr) { + return false; + } + // The checksums can be either the same or a prefix of the expected checksums, + // ending before the ':' delimiter. + size_t length = strlen(oat_boot_class_path_checksums); + if (length > boot_class_path_checksums.length() || + (length < boot_class_path_checksums.length() && boot_class_path_checksums[length] != ':')) { + return false; + } + return boot_class_path_checksums.compare(0u, length, oat_boot_class_path_checksums) == 0; } std::unique_ptr<OatFileAssistant::ImageInfo> diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index 521e419d2f..a99bd51457 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -61,6 +61,14 @@ class OatFileAssistantTest : public DexoptTest { VerifyOptimizationStatus( file, CompilerFilter::NameOfFilter(expected_filter), expected_reason); } + void InsertNewBootClasspathEntry() { + std::string extra_dex_filename = GetMultiDexSrc1(); + Runtime* runtime = Runtime::Current(); + runtime->boot_class_path_.push_back(extra_dex_filename); + if (!runtime->boot_class_path_locations_.empty()) { + runtime->boot_class_path_locations_.push_back(extra_dex_filename); + } + } }; class ScopedNonWritable { @@ -236,17 +244,50 @@ TEST_F(OatFileAssistantTest, OdexUpToDate) { Copy(GetDexSrc1(), dex_location); GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install"); - // For the use of oat location by making the dex parent not writable. - OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); + // Force the use of oat location by making the dex parent not writable. + OatFileAssistant oat_file_assistant( + dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false); EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); + + EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); + EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus()); + EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); + EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); + + VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install"); +} + +// Case: We have an ODEX file compiled against partial boot image. +// Expect: The status is kNoDexOptNeeded. +TEST_F(OatFileAssistantTest, OdexUpToDatePartialBootImage) { + std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar"; + std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex"; + Copy(GetDexSrc1(), dex_location); + GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install"); + + // Insert an extra dex file to the boot class path. + InsertNewBootClasspathEntry(); + + // Force the use of oat location by making the dex parent not writable. + OatFileAssistant oat_file_assistant( + dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false); + + EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); + EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); + EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); + EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus()); @@ -302,7 +343,7 @@ TEST_F(OatFileAssistantTest, OatUpToDate) { Copy(GetDexSrc1(), dex_location); GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); - // For the use of oat location by making the dex parent not writable. + // Force the use of oat location by making the dex parent not writable. ScopedNonWritable scoped_non_writable(dex_location); ASSERT_TRUE(scoped_non_writable.IsSuccessful()); diff --git a/runtime/runtime.h b/runtime/runtime.h index 1acb75b255..1d1d0d3937 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -91,6 +91,7 @@ class LinearAlloc; class MonitorList; class MonitorPool; class NullPointerHandler; +class OatFileAssistantTest; class OatFileManager; class Plugin; struct RuntimeArgumentMap; @@ -1145,6 +1146,7 @@ class Runtime { // Note: See comments on GetFaultMessage. friend std::string GetFaultMessageForAbortLogging(); friend class ScopedThreadPoolUsage; + friend class OatFileAssistantTest; DISALLOW_COPY_AND_ASSIGN(Runtime); }; |