summaryrefslogtreecommitdiff
path: root/dexoptanalyzer/dexoptanalyzer_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dexoptanalyzer/dexoptanalyzer_test.cc')
-rw-r--r--dexoptanalyzer/dexoptanalyzer_test.cc311
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