blob: 1703ff4cbcfdc27ecd0bc656b92db863ff03e52b [file] [log] [blame]
Calin Juravle36eb3132017-01-13 16:32:38 -08001/*
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 <gtest/gtest.h>
18
19#include "arch/instruction_set.h"
20#include "compiler_filter.h"
21#include "dexopt_test.h"
22
23namespace art {
24
25class DexoptAnalyzerTest : public DexoptTest {
26 protected:
27 std::string GetDexoptAnalyzerCmd() {
28 std::string file_path = GetTestAndroidRoot();
29 file_path += "/bin/dexoptanalyzer";
30 if (kIsDebugBuild) {
31 file_path += "d";
32 }
33 EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
34 return file_path;
35 }
36
37 int Analyze(const std::string& dex_file,
38 CompilerFilter::Filter compiler_filter,
39 bool assume_profile_changed) {
40 std::string dexoptanalyzer_cmd = GetDexoptAnalyzerCmd();
41 std::vector<std::string> argv_str;
42 argv_str.push_back(dexoptanalyzer_cmd);
43 argv_str.push_back("--dex-file=" + dex_file);
44 argv_str.push_back("--isa=" + std::string(GetInstructionSetString(kRuntimeISA)));
45 argv_str.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(compiler_filter));
46 if (assume_profile_changed) {
47 argv_str.push_back("--assume-profile-changed");
48 }
49 argv_str.push_back("--image=" + GetImageLocation());
50 argv_str.push_back("--android-data=" + android_data_);
51
52 std::string error;
53 return ExecAndReturnCode(argv_str, &error);
54 }
55
56 int DexoptanalyzerToOatFileAssistant(int dexoptanalyzerResult) {
57 switch (dexoptanalyzerResult) {
58 case 0: return OatFileAssistant::kNoDexOptNeeded;
59 case 1: return OatFileAssistant::kDex2OatFromScratch;
60 case 2: return OatFileAssistant::kDex2OatForBootImage;
61 case 3: return OatFileAssistant::kDex2OatForFilter;
62 case 4: return OatFileAssistant::kDex2OatForRelocation;
63 case 5: return -OatFileAssistant::kDex2OatForBootImage;
64 case 6: return -OatFileAssistant::kDex2OatForFilter;
65 case 7: return -OatFileAssistant::kDex2OatForRelocation;
66 default: return dexoptanalyzerResult;
67 }
68 }
69
70 // Verify that the output of dexoptanalyzer for the given arguments is the same
71 // as the output of OatFileAssistant::GetDexOptNeeded.
72 void Verify(const std::string& dex_file,
73 CompilerFilter::Filter compiler_filter,
74 bool assume_profile_changed = false) {
75 int dexoptanalyzerResult = Analyze(dex_file, compiler_filter, assume_profile_changed);
76 dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
77 OatFileAssistant oat_file_assistant(dex_file.c_str(), kRuntimeISA, /*load_executable*/ false);
78 int assistantResult = oat_file_assistant.GetDexOptNeeded(
79 compiler_filter, assume_profile_changed);
80 EXPECT_EQ(assistantResult, dexoptanalyzerResult);
81 }
82};
83
84// The tests below exercise the same test case from oat_file_assistant_test.cc.
85
86// Case: We have a DEX file, but no OAT file for it.
87TEST_F(DexoptAnalyzerTest, DexNoOat) {
88 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
89 Copy(GetDexSrc1(), dex_location);
90
91 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +010092 Verify(dex_location, CompilerFilter::kExtract);
93 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -080094 Verify(dex_location, CompilerFilter::kSpeedProfile);
95}
96
97// Case: We have a DEX file and up-to-date OAT file for it.
98TEST_F(DexoptAnalyzerTest, OatUpToDate) {
99 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
100 Copy(GetDexSrc1(), dex_location);
101 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
102
103 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100104 Verify(dex_location, CompilerFilter::kQuicken);
105 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800106 Verify(dex_location, CompilerFilter::kEverything);
107}
108
109// Case: We have a DEX file and speed-profile OAT file for it.
110TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) {
111 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
112 Copy(GetDexSrc1(), dex_location);
113 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
114
115 Verify(dex_location, CompilerFilter::kSpeedProfile, false);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100116 Verify(dex_location, CompilerFilter::kQuicken, false);
Calin Juravle36eb3132017-01-13 16:32:38 -0800117 Verify(dex_location, CompilerFilter::kSpeedProfile, true);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100118 Verify(dex_location, CompilerFilter::kQuicken, true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800119}
120
121// Case: We have a MultiDEX file and up-to-date OAT file for it.
122TEST_F(DexoptAnalyzerTest, MultiDexOatUpToDate) {
123 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
124 Copy(GetMultiDexSrc1(), dex_location);
125 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
126
127 Verify(dex_location, CompilerFilter::kSpeed, false);
128}
129
130// Case: We have a MultiDEX file where the secondary dex file is out of date.
131TEST_F(DexoptAnalyzerTest, MultiDexSecondaryOutOfDate) {
132 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
133
134 // Compile code for GetMultiDexSrc1.
135 Copy(GetMultiDexSrc1(), dex_location);
136 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
137
138 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
139 // is out of date.
140 Copy(GetMultiDexSrc2(), dex_location);
141
142 Verify(dex_location, CompilerFilter::kSpeed, false);
143}
144
145
146// Case: We have a DEX file and an OAT file out of date with respect to the
147// dex checksum.
148TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) {
149 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
150
151 // We create a dex, generate an oat for it, then overwrite the dex with a
152 // different dex to make the oat out of date.
153 Copy(GetDexSrc1(), dex_location);
154 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
155 Copy(GetDexSrc2(), dex_location);
156
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100157 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800158 Verify(dex_location, CompilerFilter::kSpeed);
159}
160
161// Case: We have a DEX file and an OAT file out of date with respect to the
162// boot image.
163TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) {
164 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
165
166 Copy(GetDexSrc1(), dex_location);
167 GenerateOatForTest(dex_location.c_str(),
168 CompilerFilter::kSpeed,
169 /*relocate*/true,
170 /*pic*/false,
171 /*with_alternate_image*/true);
172
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100173 Verify(dex_location, CompilerFilter::kExtract);
174 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800175 Verify(dex_location, CompilerFilter::kSpeed);
176}
177
178// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
179// respect to the boot image.
180// It shouldn't matter that the OAT file is out of date, because it is
181// verify-at-runtime.
182TEST_F(DexoptAnalyzerTest, OatVerifyAtRuntimeImageOutOfDate) {
183 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
184
185 Copy(GetDexSrc1(), dex_location);
186 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100187 CompilerFilter::kExtract,
Calin Juravle36eb3132017-01-13 16:32:38 -0800188 /*relocate*/true,
189 /*pic*/false,
190 /*with_alternate_image*/true);
191
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100192 Verify(dex_location, CompilerFilter::kExtract);
193 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800194}
195
196// Case: We have a DEX file and an ODEX file, but no OAT file.
197TEST_F(DexoptAnalyzerTest, DexOdexNoOat) {
198 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
199 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
200
201 Copy(GetDexSrc1(), dex_location);
202 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
203
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100204 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800205 Verify(dex_location, CompilerFilter::kSpeed);
206}
207
208// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
209TEST_F(DexoptAnalyzerTest, StrippedDexOdexNoOat) {
210 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
211 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
212
213 Copy(GetDexSrc1(), dex_location);
214 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
215
216 // Strip the dex file
217 Copy(GetStrippedDexSrc1(), dex_location);
218
219 Verify(dex_location, CompilerFilter::kSpeed);
220}
221
222// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
223TEST_F(DexoptAnalyzerTest, StrippedDexOdexOat) {
224 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
225 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
226
227 // Create the oat file from a different dex file so it looks out of date.
228 Copy(GetDexSrc2(), dex_location);
229 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
230
231 // Create the odex file
232 Copy(GetDexSrc1(), dex_location);
233 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
234
235 // Strip the dex file.
236 Copy(GetStrippedDexSrc1(), dex_location);
237
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100238 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800239 Verify(dex_location, CompilerFilter::kSpeed);
240 Verify(dex_location, CompilerFilter::kEverything);
241}
242
243// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
244// OAT file. Expect: The status is kNoDexOptNeeded.
245TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) {
246 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
247
248 Copy(GetStrippedDexSrc1(), dex_location);
249
250 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100251 Verify(dex_location, CompilerFilter::kExtract);
252 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800253}
254
255// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
256// OAT files both have patch delta of 0.
257TEST_F(DexoptAnalyzerTest, OdexOatOverlap) {
258 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
259 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
260 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
261
262 Copy(GetDexSrc1(), dex_location);
263 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
264
265 // Create the oat file by copying the odex so they are located in the same
266 // place in memory.
267 Copy(odex_location, oat_location);
268
269 Verify(dex_location, CompilerFilter::kSpeed);
270}
271
272// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
273TEST_F(DexoptAnalyzerTest, DexPicOdexNoOat) {
274 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
275 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex";
276
277 Copy(GetDexSrc1(), dex_location);
278 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
279
280 Verify(dex_location, CompilerFilter::kSpeed);
281 Verify(dex_location, CompilerFilter::kEverything);
282}
283
284// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file..
285TEST_F(DexoptAnalyzerTest, DexVerifyAtRuntimeOdexNoOat) {
286 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
287 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
288
289 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100290 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800291
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100292 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800293 Verify(dex_location, CompilerFilter::kSpeed);
294}
295
296// Case: Non-standard extension for dex file.
297TEST_F(DexoptAnalyzerTest, LongDexExtension) {
298 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
299 Copy(GetDexSrc1(), dex_location);
300
301 Verify(dex_location, CompilerFilter::kSpeed);
302}
303
304// Case: Very short, non-existent Dex location.
305TEST_F(DexoptAnalyzerTest, ShortDexLocation) {
306 std::string dex_location = "/xx";
307
308 Verify(dex_location, CompilerFilter::kSpeed);
309}
310
311} // namespace art