Home | History | Annotate | Download | only in dexlayout
      1 /*
      2  * Copyright (C) 2017 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 <string>
     18 #include <vector>
     19 
     20 #include "common_runtime_test.h"
     21 
     22 #include "runtime/exec_utils.h"
     23 #include "runtime/oat_file.h"
     24 #include "runtime/os.h"
     25 
     26 namespace art {
     27 
     28 static const char* kDexDiagContains = "--contains=core.vdex";
     29 static const char* kDexDiagContainsFails = "--contains=anything_other_than_core.vdex";
     30 static const char* kDexDiagHelp = "--help";
     31 static const char* kDexDiagVerbose = "--verbose";
     32 static const char* kDexDiagBinaryName = "dexdiag";
     33 
     34 class DexDiagTest : public CommonRuntimeTest {
     35  protected:
     36   virtual void SetUp() {
     37     CommonRuntimeTest::SetUp();
     38   }
     39 
     40   // Path to the dexdiag(d?)[32|64] binary.
     41   std::string GetDexDiagFilePath() {
     42     std::string root = GetTestAndroidRoot();
     43 
     44     root += "/bin/";
     45     root += kDexDiagBinaryName;
     46 
     47     std::string root32 = root + "32";
     48     // If we have both a 32-bit and a 64-bit build, the 32-bit file will have a 32 suffix.
     49     if (OS::FileExists(root32.c_str()) && !Is64BitInstructionSet(kRuntimeISA)) {
     50       return root32;
     51     } else {
     52       // This is a 64-bit build or only a single build exists.
     53       return root;
     54     }
     55   }
     56 
     57   std::unique_ptr<OatFile> OpenOatAndVdexFiles() {
     58     // Open the core.oat file.
     59     // This is a little convoluted because we have to
     60     // get the location of the default core image (.../framework/core.oat),
     61     // find it in the right architecture subdirectory (.../framework/arm/core.oat),
     62     // Then, opening the oat file has the side-effect of opening the corresponding
     63     // vdex file (.../framework/arm/core.vdex).
     64     const std::string default_location = GetCoreOatLocation();
     65     EXPECT_TRUE(!default_location.empty());
     66     std::string oat_location = GetSystemImageFilename(default_location.c_str(), kRuntimeISA);
     67     EXPECT_TRUE(!oat_location.empty());
     68     std::cout << "==" << oat_location << std::endl;
     69     std::string error_msg;
     70     std::unique_ptr<OatFile> oat(OatFile::Open(oat_location.c_str(),
     71                                                oat_location.c_str(),
     72                                                nullptr,
     73                                                nullptr,
     74                                                false,
     75                                                /*low_4gb*/false,
     76                                                nullptr,
     77                                                &error_msg));
     78     EXPECT_TRUE(oat != nullptr) << error_msg;
     79     return oat;
     80   }
     81 
     82   // Run dexdiag with a custom boot image location.
     83   bool Exec(pid_t this_pid, const std::vector<std::string>& args, std::string* error_msg) {
     84     // Invoke 'dexdiag' against the current process.
     85     // This should succeed because we have a runtime and so it should
     86     // be able to map in the boot.art and do a diff for it.
     87     std::vector<std::string> exec_argv;
     88 
     89     // Build the command line "dexdiag <args> this_pid".
     90     std::string executable_path = GetDexDiagFilePath();
     91     EXPECT_TRUE(OS::FileExists(executable_path.c_str())) << executable_path
     92                                                          << " should be a valid file path";
     93     exec_argv.push_back(executable_path);
     94     for (const auto& arg : args) {
     95       exec_argv.push_back(arg);
     96     }
     97     exec_argv.push_back(std::to_string(this_pid));
     98 
     99     return ::art::Exec(exec_argv, error_msg);
    100   }
    101 };
    102 
    103 // We can't run these tests on the host, as they will fail when trying to open
    104 // /proc/pid/pagemap.
    105 // On the target, we invoke 'dexdiag' against the current process.
    106 // This should succeed because we have a runtime and so dexdiag should
    107 // be able to find the map for, e.g., boot.vdex and friends.
    108 TEST_F(DexDiagTest, DexDiagHelpTest) {
    109   // TODO: test the resulting output.
    110   std::string error_msg;
    111   ASSERT_TRUE(Exec(getpid(), { kDexDiagHelp }, &error_msg)) << "Failed to execute -- because: "
    112                                                             << error_msg;
    113 }
    114 
    115 #if defined (ART_TARGET)
    116 TEST_F(DexDiagTest, DexDiagContainsTest) {
    117 #else
    118 TEST_F(DexDiagTest, DISABLED_DexDiagContainsTest) {
    119 #endif
    120   std::unique_ptr<OatFile> oat = OpenOatAndVdexFiles();
    121   // TODO: test the resulting output.
    122   std::string error_msg;
    123   ASSERT_TRUE(Exec(getpid(), { kDexDiagContains }, &error_msg)) << "Failed to execute -- because: "
    124                                                                 << error_msg;
    125 }
    126 
    127 #if defined (ART_TARGET)
    128 TEST_F(DexDiagTest, DexDiagContainsFailsTest) {
    129 #else
    130 TEST_F(DexDiagTest, DISABLED_DexDiagContainsFailsTest) {
    131 #endif
    132   std::unique_ptr<OatFile> oat = OpenOatAndVdexFiles();
    133   // TODO: test the resulting output.
    134   std::string error_msg;
    135   ASSERT_FALSE(Exec(getpid(), { kDexDiagContainsFails }, &error_msg))
    136       << "Failed to execute -- because: "
    137       << error_msg;
    138 }
    139 
    140 #if defined (ART_TARGET)
    141 TEST_F(DexDiagTest, DexDiagVerboseTest) {
    142 #else
    143 TEST_F(DexDiagTest, DISABLED_DexDiagVerboseTest) {
    144 #endif
    145   // TODO: test the resulting output.
    146   std::unique_ptr<OatFile> oat = OpenOatAndVdexFiles();
    147   std::string error_msg;
    148   ASSERT_TRUE(Exec(getpid(), { kDexDiagVerbose }, &error_msg)) << "Failed to execute -- because: "
    149                                                                << error_msg;
    150 }
    151 
    152 }  // namespace art
    153