blob: 9f8dbd7b0e551a5582d7f096e2ec48e92b16189d [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() {
Roland Levillainfb6a5c02019-03-29 20:20:16 +000028 std::string file_path = GetAndroidRuntimeBinDir() + "/dexoptanalyzer";
Calin Juravle36eb3132017-01-13 16:32:38 -080029 if (kIsDebugBuild) {
Roland Levillainfb6a5c02019-03-29 20:20:16 +000030 file_path += 'd';
Calin Juravle36eb3132017-01-13 16:32:38 -080031 }
32 EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
33 return file_path;
34 }
35
36 int Analyze(const std::string& dex_file,
37 CompilerFilter::Filter compiler_filter,
Nicolas Geoffray35de14b2019-01-10 13:10:36 +000038 bool assume_profile_changed,
39 const std::string& class_loader_context) {
Calin Juravle36eb3132017-01-13 16:32:38 -080040 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 }
Vladimir Marko7a85e702018-12-03 18:47:23 +000049 argv_str.push_back("--runtime-arg");
50 argv_str.push_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()));
51 argv_str.push_back("--runtime-arg");
52 argv_str.push_back(GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
Calin Juravle36eb3132017-01-13 16:32:38 -080053 argv_str.push_back("--image=" + GetImageLocation());
54 argv_str.push_back("--android-data=" + android_data_);
Nicolas Geoffray35de14b2019-01-10 13:10:36 +000055 if (!class_loader_context.empty()) {
56 argv_str.push_back("--class-loader-context=" + class_loader_context);
57 }
Calin Juravle36eb3132017-01-13 16:32:38 -080058
59 std::string error;
60 return ExecAndReturnCode(argv_str, &error);
61 }
62
63 int DexoptanalyzerToOatFileAssistant(int dexoptanalyzerResult) {
64 switch (dexoptanalyzerResult) {
65 case 0: return OatFileAssistant::kNoDexOptNeeded;
66 case 1: return OatFileAssistant::kDex2OatFromScratch;
67 case 2: return OatFileAssistant::kDex2OatForBootImage;
68 case 3: return OatFileAssistant::kDex2OatForFilter;
Vladimir Markoe0669322018-09-03 15:44:54 +010069 case 4: return -OatFileAssistant::kDex2OatForBootImage;
70 case 5: return -OatFileAssistant::kDex2OatForFilter;
Calin Juravle36eb3132017-01-13 16:32:38 -080071 default: return dexoptanalyzerResult;
72 }
73 }
74
75 // Verify that the output of dexoptanalyzer for the given arguments is the same
76 // as the output of OatFileAssistant::GetDexOptNeeded.
77 void Verify(const std::string& dex_file,
78 CompilerFilter::Filter compiler_filter,
Shubham Ajmerae4e812a2017-05-25 20:09:58 -070079 bool assume_profile_changed = false,
Nicolas Geoffray35de14b2019-01-10 13:10:36 +000080 bool downgrade = false,
81 const std::string& class_loader_context = "") {
82 int dexoptanalyzerResult = Analyze(
83 dex_file, compiler_filter, assume_profile_changed, class_loader_context);
Calin Juravle36eb3132017-01-13 16:32:38 -080084 dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
Andreas Gampe9b031f72018-10-04 11:03:34 -070085 OatFileAssistant oat_file_assistant(dex_file.c_str(), kRuntimeISA, /*load_executable=*/ false);
Calin Juravle36eb3132017-01-13 16:32:38 -080086 int assistantResult = oat_file_assistant.GetDexOptNeeded(
Shubham Ajmerae4e812a2017-05-25 20:09:58 -070087 compiler_filter, assume_profile_changed, downgrade);
Calin Juravle36eb3132017-01-13 16:32:38 -080088 EXPECT_EQ(assistantResult, dexoptanalyzerResult);
89 }
90};
91
92// The tests below exercise the same test case from oat_file_assistant_test.cc.
93
94// Case: We have a DEX file, but no OAT file for it.
95TEST_F(DexoptAnalyzerTest, DexNoOat) {
96 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
97 Copy(GetDexSrc1(), dex_location);
98
99 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100100 Verify(dex_location, CompilerFilter::kExtract);
101 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800102 Verify(dex_location, CompilerFilter::kSpeedProfile);
103}
104
105// Case: We have a DEX file and up-to-date OAT file for it.
106TEST_F(DexoptAnalyzerTest, OatUpToDate) {
107 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
108 Copy(GetDexSrc1(), dex_location);
109 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
110
111 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100112 Verify(dex_location, CompilerFilter::kQuicken);
113 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800114 Verify(dex_location, CompilerFilter::kEverything);
115}
116
117// Case: We have a DEX file and speed-profile OAT file for it.
118TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) {
119 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
120 Copy(GetDexSrc1(), dex_location);
121 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
122
123 Verify(dex_location, CompilerFilter::kSpeedProfile, false);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100124 Verify(dex_location, CompilerFilter::kQuicken, false);
Calin Juravle36eb3132017-01-13 16:32:38 -0800125 Verify(dex_location, CompilerFilter::kSpeedProfile, true);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100126 Verify(dex_location, CompilerFilter::kQuicken, true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800127}
128
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700129TEST_F(DexoptAnalyzerTest, Downgrade) {
130 std::string dex_location = GetScratchDir() + "/Downgrade.jar";
131 Copy(GetDexSrc1(), dex_location);
132 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
133
134 Verify(dex_location, CompilerFilter::kSpeedProfile, false, true);
135 Verify(dex_location, CompilerFilter::kQuicken, false, true);
136 Verify(dex_location, CompilerFilter::kVerify, false, true);
137}
138
Calin Juravle36eb3132017-01-13 16:32:38 -0800139// Case: We have a MultiDEX file and up-to-date OAT file for it.
140TEST_F(DexoptAnalyzerTest, MultiDexOatUpToDate) {
141 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
142 Copy(GetMultiDexSrc1(), dex_location);
143 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
144
145 Verify(dex_location, CompilerFilter::kSpeed, false);
146}
147
148// Case: We have a MultiDEX file where the secondary dex file is out of date.
149TEST_F(DexoptAnalyzerTest, MultiDexSecondaryOutOfDate) {
150 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
151
152 // Compile code for GetMultiDexSrc1.
153 Copy(GetMultiDexSrc1(), dex_location);
154 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
155
156 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
157 // is out of date.
158 Copy(GetMultiDexSrc2(), dex_location);
159
160 Verify(dex_location, CompilerFilter::kSpeed, false);
161}
162
163
164// Case: We have a DEX file and an OAT file out of date with respect to the
165// dex checksum.
166TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) {
167 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
168
169 // We create a dex, generate an oat for it, then overwrite the dex with a
170 // different dex to make the oat out of date.
171 Copy(GetDexSrc1(), dex_location);
172 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
173 Copy(GetDexSrc2(), dex_location);
174
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100175 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800176 Verify(dex_location, CompilerFilter::kSpeed);
177}
178
179// Case: We have a DEX file and an OAT file out of date with respect to the
180// boot image.
181TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) {
182 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
183
184 Copy(GetDexSrc1(), dex_location);
185 GenerateOatForTest(dex_location.c_str(),
186 CompilerFilter::kSpeed,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700187 /*with_alternate_image=*/true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800188
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100189 Verify(dex_location, CompilerFilter::kExtract);
190 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800191 Verify(dex_location, CompilerFilter::kSpeed);
192}
193
194// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
195// respect to the boot image.
196// It shouldn't matter that the OAT file is out of date, because it is
197// verify-at-runtime.
198TEST_F(DexoptAnalyzerTest, OatVerifyAtRuntimeImageOutOfDate) {
199 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
200
201 Copy(GetDexSrc1(), dex_location);
202 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100203 CompilerFilter::kExtract,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700204 /*with_alternate_image=*/true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800205
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100206 Verify(dex_location, CompilerFilter::kExtract);
207 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800208}
209
210// Case: We have a DEX file and an ODEX file, but no OAT file.
211TEST_F(DexoptAnalyzerTest, DexOdexNoOat) {
212 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
213 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
214
215 Copy(GetDexSrc1(), dex_location);
216 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
217
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100218 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800219 Verify(dex_location, CompilerFilter::kSpeed);
Vladimir Markoa2da9b92018-10-10 14:21:55 +0100220 Verify(dex_location, CompilerFilter::kEverything);
Calin Juravle36eb3132017-01-13 16:32:38 -0800221}
222
223// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
224TEST_F(DexoptAnalyzerTest, StrippedDexOdexNoOat) {
225 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
226 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
227
228 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100229 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle36eb3132017-01-13 16:32:38 -0800230
231 // Strip the dex file
232 Copy(GetStrippedDexSrc1(), dex_location);
233
234 Verify(dex_location, CompilerFilter::kSpeed);
235}
236
237// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
238TEST_F(DexoptAnalyzerTest, StrippedDexOdexOat) {
239 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
240 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
241
242 // Create the oat file from a different dex file so it looks out of date.
243 Copy(GetDexSrc2(), dex_location);
244 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
245
246 // Create the odex file
247 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100248 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle36eb3132017-01-13 16:32:38 -0800249
250 // Strip the dex file.
251 Copy(GetStrippedDexSrc1(), dex_location);
252
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100253 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800254 Verify(dex_location, CompilerFilter::kSpeed);
255 Verify(dex_location, CompilerFilter::kEverything);
256}
257
258// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
259// OAT file. Expect: The status is kNoDexOptNeeded.
260TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) {
261 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
262
263 Copy(GetStrippedDexSrc1(), dex_location);
264
265 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100266 Verify(dex_location, CompilerFilter::kExtract);
267 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800268}
269
Vladimir Markoe0669322018-09-03 15:44:54 +0100270// Case: We have a DEX file, an ODEX file and an OAT file.
Calin Juravle36eb3132017-01-13 16:32:38 -0800271TEST_F(DexoptAnalyzerTest, OdexOatOverlap) {
272 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
273 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
274 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
275
276 Copy(GetDexSrc1(), dex_location);
277 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
278
279 // Create the oat file by copying the odex so they are located in the same
280 // place in memory.
281 Copy(odex_location, oat_location);
282
283 Verify(dex_location, CompilerFilter::kSpeed);
284}
285
Calin Juravle36eb3132017-01-13 16:32:38 -0800286// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file..
287TEST_F(DexoptAnalyzerTest, DexVerifyAtRuntimeOdexNoOat) {
288 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
289 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
290
291 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100292 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800293
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100294 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800295 Verify(dex_location, CompilerFilter::kSpeed);
296}
297
298// Case: Non-standard extension for dex file.
299TEST_F(DexoptAnalyzerTest, LongDexExtension) {
300 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
301 Copy(GetDexSrc1(), dex_location);
302
303 Verify(dex_location, CompilerFilter::kSpeed);
304}
305
306// Case: Very short, non-existent Dex location.
307TEST_F(DexoptAnalyzerTest, ShortDexLocation) {
308 std::string dex_location = "/xx";
309
310 Verify(dex_location, CompilerFilter::kSpeed);
311}
312
Nicolas Geoffray35de14b2019-01-10 13:10:36 +0000313// Case: We have a DEX file and up-to-date OAT file for it, and we check with
314// a class loader context.
315TEST_F(DexoptAnalyzerTest, ClassLoaderContext) {
316 std::string dex_location1 = GetScratchDir() + "/DexToAnalyze.jar";
317 std::string odex_location1 = GetOdexDir() + "/DexToAnalyze.odex";
318 std::string dex_location2 = GetScratchDir() + "/DexInContext.jar";
319 Copy(GetDexSrc1(), dex_location1);
320 Copy(GetDexSrc2(), dex_location2);
321
322 std::string class_loader_context = "PCL[" + dex_location2 + "]";
323 std::string class_loader_context_option = "--class-loader-context=PCL[" + dex_location2 + "]";
324
325 // Generate the odex to get the class loader context also open the dex files.
326 GenerateOdexForTest(dex_location1, odex_location1, CompilerFilter::kSpeed, /* compilation_reason= */ nullptr, /* extra_args= */ { class_loader_context_option });
327
328 Verify(dex_location1, CompilerFilter::kSpeed, false, false, class_loader_context);
329}
330
Calin Juravle36eb3132017-01-13 16:32:38 -0800331} // namespace art