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