diff options
Diffstat (limited to 'dexoptanalyzer/dexoptanalyzer_test.cc')
| -rw-r--r-- | dexoptanalyzer/dexoptanalyzer_test.cc | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/dexoptanalyzer/dexoptanalyzer_test.cc b/dexoptanalyzer/dexoptanalyzer_test.cc new file mode 100644 index 0000000000..57d3f1f68b --- /dev/null +++ b/dexoptanalyzer/dexoptanalyzer_test.cc @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gtest/gtest.h> + +#include "arch/instruction_set.h" +#include "compiler_filter.h" +#include "dexopt_test.h" + +namespace art { + +class DexoptAnalyzerTest : public DexoptTest { + protected: + std::string GetDexoptAnalyzerCmd() { + std::string file_path = GetTestAndroidRoot(); + file_path += "/bin/dexoptanalyzer"; + if (kIsDebugBuild) { + file_path += "d"; + } + EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path"; + return file_path; + } + + int Analyze(const std::string& dex_file, + CompilerFilter::Filter compiler_filter, + bool assume_profile_changed) { + std::string dexoptanalyzer_cmd = GetDexoptAnalyzerCmd(); + std::vector<std::string> argv_str; + argv_str.push_back(dexoptanalyzer_cmd); + argv_str.push_back("--dex-file=" + dex_file); + argv_str.push_back("--isa=" + std::string(GetInstructionSetString(kRuntimeISA))); + argv_str.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(compiler_filter)); + if (assume_profile_changed) { + argv_str.push_back("--assume-profile-changed"); + } + argv_str.push_back("--image=" + GetImageLocation()); + argv_str.push_back("--android-data=" + android_data_); + + std::string error; + return ExecAndReturnCode(argv_str, &error); + } + + int DexoptanalyzerToOatFileAssistant(int dexoptanalyzerResult) { + switch (dexoptanalyzerResult) { + case 0: return OatFileAssistant::kNoDexOptNeeded; + case 1: return OatFileAssistant::kDex2OatFromScratch; + case 2: return OatFileAssistant::kDex2OatForBootImage; + case 3: return OatFileAssistant::kDex2OatForFilter; + case 4: return OatFileAssistant::kDex2OatForRelocation; + case 5: return -OatFileAssistant::kDex2OatForBootImage; + case 6: return -OatFileAssistant::kDex2OatForFilter; + case 7: return -OatFileAssistant::kDex2OatForRelocation; + default: return dexoptanalyzerResult; + } + } + + // Verify that the output of dexoptanalyzer for the given arguments is the same + // as the output of OatFileAssistant::GetDexOptNeeded. + void Verify(const std::string& dex_file, + CompilerFilter::Filter compiler_filter, + bool assume_profile_changed = false) { + int dexoptanalyzerResult = Analyze(dex_file, compiler_filter, assume_profile_changed); + dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult); + OatFileAssistant oat_file_assistant(dex_file.c_str(), kRuntimeISA, /*load_executable*/ false); + int assistantResult = oat_file_assistant.GetDexOptNeeded( + compiler_filter, assume_profile_changed); + EXPECT_EQ(assistantResult, dexoptanalyzerResult); + } +}; + +// The tests below exercise the same test case from oat_file_assistant_test.cc. + +// Case: We have a DEX file, but no OAT file for it. +TEST_F(DexoptAnalyzerTest, DexNoOat) { + std::string dex_location = GetScratchDir() + "/DexNoOat.jar"; + Copy(GetDexSrc1(), dex_location); + + Verify(dex_location, CompilerFilter::kSpeed); + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kInterpretOnly); + Verify(dex_location, CompilerFilter::kSpeedProfile); +} + +// Case: We have a DEX file and up-to-date OAT file for it. +TEST_F(DexoptAnalyzerTest, OatUpToDate) { + std::string dex_location = GetScratchDir() + "/OatUpToDate.jar"; + Copy(GetDexSrc1(), dex_location); + GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); + + Verify(dex_location, CompilerFilter::kSpeed); + Verify(dex_location, CompilerFilter::kInterpretOnly); + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kEverything); +} + +// Case: We have a DEX file and speed-profile OAT file for it. +TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) { + std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar"; + Copy(GetDexSrc1(), dex_location); + GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile); + + Verify(dex_location, CompilerFilter::kSpeedProfile, false); + Verify(dex_location, CompilerFilter::kInterpretOnly, false); + Verify(dex_location, CompilerFilter::kSpeedProfile, true); + Verify(dex_location, CompilerFilter::kInterpretOnly, true); +} + +// Case: We have a MultiDEX file and up-to-date OAT file for it. +TEST_F(DexoptAnalyzerTest, MultiDexOatUpToDate) { + std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar"; + Copy(GetMultiDexSrc1(), dex_location); + GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); + + Verify(dex_location, CompilerFilter::kSpeed, false); +} + +// Case: We have a MultiDEX file where the secondary dex file is out of date. +TEST_F(DexoptAnalyzerTest, MultiDexSecondaryOutOfDate) { + std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar"; + + // Compile code for GetMultiDexSrc1. + Copy(GetMultiDexSrc1(), dex_location); + GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); + + // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum + // is out of date. + Copy(GetMultiDexSrc2(), dex_location); + + Verify(dex_location, CompilerFilter::kSpeed, false); +} + + +// Case: We have a DEX file and an OAT file out of date with respect to the +// dex checksum. +TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) { + std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar"; + + // We create a dex, generate an oat for it, then overwrite the dex with a + // different dex to make the oat out of date. + Copy(GetDexSrc1(), dex_location); + GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); + Copy(GetDexSrc2(), dex_location); + + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kSpeed); +} + +// Case: We have a DEX file and an OAT file out of date with respect to the +// boot image. +TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) { + std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar"; + + Copy(GetDexSrc1(), dex_location); + GenerateOatForTest(dex_location.c_str(), + CompilerFilter::kSpeed, + /*relocate*/true, + /*pic*/false, + /*with_alternate_image*/true); + + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kInterpretOnly); + Verify(dex_location, CompilerFilter::kSpeed); +} + +// Case: We have a DEX file and a verify-at-runtime OAT file out of date with +// respect to the boot image. +// It shouldn't matter that the OAT file is out of date, because it is +// verify-at-runtime. +TEST_F(DexoptAnalyzerTest, OatVerifyAtRuntimeImageOutOfDate) { + std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar"; + + Copy(GetDexSrc1(), dex_location); + GenerateOatForTest(dex_location.c_str(), + CompilerFilter::kVerifyAtRuntime, + /*relocate*/true, + /*pic*/false, + /*with_alternate_image*/true); + + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kInterpretOnly); +} + +// Case: We have a DEX file and an ODEX file, but no OAT file. +TEST_F(DexoptAnalyzerTest, DexOdexNoOat) { + std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar"; + std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex"; + + Copy(GetDexSrc1(), dex_location); + GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); + + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kSpeed); +} + +// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file. +TEST_F(DexoptAnalyzerTest, StrippedDexOdexNoOat) { + std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar"; + std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex"; + + Copy(GetDexSrc1(), dex_location); + GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); + + // Strip the dex file + Copy(GetStrippedDexSrc1(), dex_location); + + Verify(dex_location, CompilerFilter::kSpeed); +} + +// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file. +TEST_F(DexoptAnalyzerTest, StrippedDexOdexOat) { + std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar"; + std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex"; + + // Create the oat file from a different dex file so it looks out of date. + Copy(GetDexSrc2(), dex_location); + GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); + + // Create the odex file + Copy(GetDexSrc1(), dex_location); + GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); + + // Strip the dex file. + Copy(GetStrippedDexSrc1(), dex_location); + + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kSpeed); + Verify(dex_location, CompilerFilter::kEverything); +} + +// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no +// OAT file. Expect: The status is kNoDexOptNeeded. +TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) { + std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar"; + + Copy(GetStrippedDexSrc1(), dex_location); + + Verify(dex_location, CompilerFilter::kSpeed); + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kInterpretOnly); +} + +// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and +// OAT files both have patch delta of 0. +TEST_F(DexoptAnalyzerTest, OdexOatOverlap) { + std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar"; + std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex"; + std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat"; + + Copy(GetDexSrc1(), dex_location); + GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); + + // Create the oat file by copying the odex so they are located in the same + // place in memory. + Copy(odex_location, oat_location); + + Verify(dex_location, CompilerFilter::kSpeed); +} + +// Case: We have a DEX file and a PIC ODEX file, but no OAT file. +TEST_F(DexoptAnalyzerTest, DexPicOdexNoOat) { + std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar"; + std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex"; + + Copy(GetDexSrc1(), dex_location); + GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); + + Verify(dex_location, CompilerFilter::kSpeed); + Verify(dex_location, CompilerFilter::kEverything); +} + +// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.. +TEST_F(DexoptAnalyzerTest, DexVerifyAtRuntimeOdexNoOat) { + std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar"; + std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex"; + + Copy(GetDexSrc1(), dex_location); + GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerifyAtRuntime); + + Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kSpeed); +} + +// Case: Non-standard extension for dex file. +TEST_F(DexoptAnalyzerTest, LongDexExtension) { + std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx"; + Copy(GetDexSrc1(), dex_location); + + Verify(dex_location, CompilerFilter::kSpeed); +} + +// Case: Very short, non-existent Dex location. +TEST_F(DexoptAnalyzerTest, ShortDexLocation) { + std::string dex_location = "/xx"; + + Verify(dex_location, CompilerFilter::kSpeed); +} + +} // namespace art |