diff options
Diffstat (limited to 'dexlayout/dexlayout_test.cc')
| -rw-r--r-- | dexlayout/dexlayout_test.cc | 155 |
1 files changed, 141 insertions, 14 deletions
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc index 877ea923fc..6fe8eeb66e 100644 --- a/dexlayout/dexlayout_test.cc +++ b/dexlayout/dexlayout_test.cc @@ -23,7 +23,9 @@ #include "base/unix_file/fd_file.h" #include "common_runtime_test.h" +#include "dex_file-inl.h" #include "exec_utils.h" +#include "jit/profile_compilation_info.h" #include "utils.h" namespace art { @@ -40,9 +42,6 @@ static const char kDexFileLayoutInputDex[] = "qAAAAAYAAAACAAAAwAAAAAEgAAACAAAAAAEAAAIgAAAHAAAAMAEAAAMgAAACAAAAaQEAAAAgAAAC" "AAAAdQEAAAAQAAABAAAAjAEAAA=="; -static const char kDexFileLayoutInputProfile[] = - "cHJvADAwNQABCwABAAAAAAD1KW3+Y2xhc3Nlcy5kZXgBAA=="; - // Dex file with catch handler unreferenced by try blocks. // Constructed by building a dex file with try/catch blocks and hex editing. static const char kUnreferencedCatchHandlerInputDex[] = @@ -317,6 +316,68 @@ class DexLayoutTest : public CommonRuntimeTest { return true; } + // Create a profile with some subset of methods and classes. + void CreateProfile(const std::string& input_dex, + const std::string& out_profile, + const std::string& dex_location) { + std::vector<std::unique_ptr<const DexFile>> dex_files; + std::string error_msg; + bool result = DexFile::Open(input_dex.c_str(), + input_dex, + false, + &error_msg, + &dex_files); + + ASSERT_TRUE(result) << error_msg; + ASSERT_GE(dex_files.size(), 1u); + + size_t profile_methods = 0; + size_t profile_classes = 0; + ProfileCompilationInfo pfi; + std::vector<ProfileMethodInfo> pmis; + std::set<DexCacheResolvedClasses> classes; + for (const std::unique_ptr<const DexFile>& dex_file : dex_files) { + for (uint32_t i = 0; i < dex_file->NumMethodIds(); i += 2) { + if ((i & 3) != 0) { + pfi.AddMethodIndex(dex_location, + dex_file->GetLocationChecksum(), + i, + dex_file->NumMethodIds()); + ++profile_methods; + } else if ((i & 2) != 0) { + pfi.AddSampledMethod(/*startup*/true, + dex_location, + dex_file->GetLocationChecksum(), + i, + dex_file->NumMethodIds()); + ++profile_methods; + } + } + DexCacheResolvedClasses cur_classes(dex_location, + dex_location, + dex_file->GetLocationChecksum(), + dex_file->NumMethodIds()); + // Add every even class too. + for (uint32_t i = 0; i < dex_file->NumClassDefs(); i += 1) { + if ((i & 2) == 0) { + cur_classes.AddClass(dex_file->GetClassDef(i).class_idx_); + ++profile_classes; + } + } + classes.insert(cur_classes); + } + pfi.AddMethodsAndClasses(pmis, classes); + // Write to provided file. + std::unique_ptr<File> file(OS::CreateEmptyFile(out_profile.c_str())); + ASSERT_TRUE(file != nullptr); + pfi.Save(file->Fd()); + if (file->FlushCloseOrErase() != 0) { + PLOG(FATAL) << "Could not flush and close test file."; + } + EXPECT_GE(profile_methods, 0u); + EXPECT_GE(profile_classes, 0u); + } + // Runs DexFileLayout test. bool DexFileLayoutExec(std::string* error_msg) { ScratchFile tmp_file; @@ -328,7 +389,8 @@ class DexLayoutTest : public CommonRuntimeTest { std::string dex_file = tmp_dir + "classes.dex"; WriteFileBase64(kDexFileLayoutInputDex, dex_file.c_str()); std::string profile_file = tmp_dir + "primary.prof"; - WriteFileBase64(kDexFileLayoutInputProfile, profile_file.c_str()); + CreateProfile(dex_file, profile_file, dex_file); + // WriteFileBase64(kDexFileLayoutInputProfile, profile_file.c_str()); std::string output_dex = tmp_dir + "classes.dex.new"; std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout"; @@ -350,6 +412,73 @@ class DexLayoutTest : public CommonRuntimeTest { return true; } + // Runs DexFileLayout test twice (second time is run on output of first time) + // for behavior consistency. + bool DexFileLayoutFixedPointExec(std::string* error_msg) { + ScratchFile tmp_file; + std::string tmp_name = tmp_file.GetFilename(); + size_t tmp_last_slash = tmp_name.rfind("/"); + std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1); + + // Unzip the test dex file to the classes.dex destination. It is required to unzip since + // opening from jar recalculates the dex location checksum. + std::string dex_file = tmp_dir + "classes.dex"; + + std::vector<std::string> unzip_args = { + "/usr/bin/unzip", + GetTestDexFileName("ManyMethods"), + "classes.dex", + "-d", + tmp_dir, + }; + if (!art::Exec(unzip_args, error_msg)) { + LOG(ERROR) << "Failed to unzip dex"; + return false; + } + + std::string profile_file = tmp_dir + "primary.prof"; + CreateProfile(dex_file, profile_file, dex_file); + std::string output_dex = tmp_dir + "classes.dex.new"; + std::string second_output_dex = tmp_dir + "classes.dex.new.new"; + + std::string dexlayout = GetTestAndroidRoot() + "/bin/dexlayout"; + EXPECT_TRUE(OS::FileExists(dexlayout.c_str())) << dexlayout << " should be a valid file path"; + + // -v makes sure that the layout did not corrupt the dex file. + std::vector<std::string> dexlayout_exec_argv = + { dexlayout, "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, dex_file }; + if (!::art::Exec(dexlayout_exec_argv, error_msg)) { + return false; + } + + // Recreate the profile with the new dex location. This is required so that the profile dex + // location matches. + CreateProfile(dex_file, profile_file, output_dex); + + // -v makes sure that the layout did not corrupt the dex file. + // -i since the checksum won't match from the first layout. + std::vector<std::string> second_dexlayout_exec_argv = + { dexlayout, "-i", "-v", "-w", tmp_dir, "-o", tmp_name, "-p", profile_file, output_dex }; + if (!::art::Exec(second_dexlayout_exec_argv, error_msg)) { + return false; + } + + bool diff_result = true; + std::vector<std::string> diff_exec_argv = + { "/usr/bin/diff", output_dex, second_output_dex }; + if (!::art::Exec(diff_exec_argv, error_msg)) { + diff_result = false; + } + + std::vector<std::string> rm_exec_argv = + { "/bin/rm", dex_file, profile_file, output_dex, second_output_dex }; + if (!::art::Exec(rm_exec_argv, error_msg)) { + return false; + } + + return diff_result; + } + // Runs UnreferencedCatchHandlerTest & Unreferenced0SizeCatchHandlerTest. bool UnreferencedCatchHandlerExec(std::string* error_msg, const char* filename) { ScratchFile tmp_file; @@ -387,13 +516,11 @@ class DexLayoutTest : public CommonRuntimeTest { bool DexLayoutExec(ScratchFile* dex_file, const char* dex_filename, ScratchFile* profile_file, - const char* profile_filename, std::vector<std::string>& dexlayout_exec_argv) { WriteBase64ToFile(dex_filename, dex_file->GetFile()); EXPECT_EQ(dex_file->GetFile()->Flush(), 0); if (profile_file != nullptr) { - WriteBase64ToFile(profile_filename, profile_file->GetFile()); - EXPECT_EQ(profile_file->GetFile()->Flush(), 0); + CreateProfile(dex_file->GetFilename(), profile_file->GetFilename(), dex_file->GetFilename()); } std::string error_msg; const bool result = ::art::Exec(dexlayout_exec_argv, &error_msg); @@ -427,6 +554,13 @@ TEST_F(DexLayoutTest, DexFileLayout) { ASSERT_TRUE(DexFileLayoutExec(&error_msg)) << error_msg; } +TEST_F(DexLayoutTest, DexFileLayoutFixedPoint) { + // Disable test on target. + TEST_DISABLED_FOR_TARGET(); + std::string error_msg; + ASSERT_TRUE(DexFileLayoutFixedPointExec(&error_msg)) << error_msg; +} + TEST_F(DexLayoutTest, UnreferencedCatchHandler) { // Disable test on target. TEST_DISABLED_FOR_TARGET(); @@ -460,7 +594,6 @@ TEST_F(DexLayoutTest, DuplicateOffset) { ASSERT_TRUE(DexLayoutExec(&temp_dex, kDexFileDuplicateOffset, nullptr /* profile_file */, - nullptr /* profile_filename */, dexlayout_exec_argv)); } @@ -473,7 +606,6 @@ TEST_F(DexLayoutTest, NullSetRefListElement) { ASSERT_TRUE(DexLayoutExec(&temp_dex, kNullSetRefListElementInputDex, nullptr /* profile_file */, - nullptr /* profile_filename */, dexlayout_exec_argv)); } @@ -487,7 +619,6 @@ TEST_F(DexLayoutTest, MultiClassData) { ASSERT_TRUE(DexLayoutExec(&temp_dex, kMultiClassDataInputDex, &temp_profile, - kDexFileLayoutInputProfile, dexlayout_exec_argv)); } @@ -501,7 +632,6 @@ TEST_F(DexLayoutTest, UnalignedCodeInfo) { ASSERT_TRUE(DexLayoutExec(&temp_dex, kUnalignedCodeInfoInputDex, &temp_profile, - kDexFileLayoutInputProfile, dexlayout_exec_argv)); } @@ -515,7 +645,6 @@ TEST_F(DexLayoutTest, ClassDataBeforeCode) { ASSERT_TRUE(DexLayoutExec(&temp_dex, kClassDataBeforeCodeInputDex, &temp_profile, - kDexFileLayoutInputProfile, dexlayout_exec_argv)); } @@ -528,7 +657,6 @@ TEST_F(DexLayoutTest, UnknownTypeDebugInfo) { ASSERT_TRUE(DexLayoutExec(&temp_dex, kUnknownTypeDebugInfoInputDex, nullptr /* profile_file */, - nullptr /* profile_filename */, dexlayout_exec_argv)); } @@ -541,7 +669,6 @@ TEST_F(DexLayoutTest, DuplicateCodeItem) { ASSERT_TRUE(DexLayoutExec(&temp_dex, kDuplicateCodeItemInputDex, nullptr /* profile_file */, - nullptr /* profile_filename */, dexlayout_exec_argv)); } |