blob: 7b6b36c133fa3e9ff48db3e2a5460f2a9b772968 [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,
Nicolas Geoffray35de14b2019-01-10 13:10:36 +000039 bool assume_profile_changed,
40 const std::string& class_loader_context) {
Calin Juravle36eb3132017-01-13 16:32:38 -080041 std::string dexoptanalyzer_cmd = GetDexoptAnalyzerCmd();
42 std::vector<std::string> argv_str;
43 argv_str.push_back(dexoptanalyzer_cmd);
44 argv_str.push_back("--dex-file=" + dex_file);
45 argv_str.push_back("--isa=" + std::string(GetInstructionSetString(kRuntimeISA)));
46 argv_str.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(compiler_filter));
47 if (assume_profile_changed) {
48 argv_str.push_back("--assume-profile-changed");
49 }
Vladimir Marko7a85e702018-12-03 18:47:23 +000050 argv_str.push_back("--runtime-arg");
51 argv_str.push_back(GetClassPathOption("-Xbootclasspath:", GetLibCoreDexFileNames()));
52 argv_str.push_back("--runtime-arg");
53 argv_str.push_back(GetClassPathOption("-Xbootclasspath-locations:", GetLibCoreDexLocations()));
Calin Juravle36eb3132017-01-13 16:32:38 -080054 argv_str.push_back("--image=" + GetImageLocation());
55 argv_str.push_back("--android-data=" + android_data_);
Nicolas Geoffray35de14b2019-01-10 13:10:36 +000056 if (!class_loader_context.empty()) {
57 argv_str.push_back("--class-loader-context=" + class_loader_context);
58 }
Calin Juravle36eb3132017-01-13 16:32:38 -080059
60 std::string error;
61 return ExecAndReturnCode(argv_str, &error);
62 }
63
64 int DexoptanalyzerToOatFileAssistant(int dexoptanalyzerResult) {
65 switch (dexoptanalyzerResult) {
66 case 0: return OatFileAssistant::kNoDexOptNeeded;
67 case 1: return OatFileAssistant::kDex2OatFromScratch;
68 case 2: return OatFileAssistant::kDex2OatForBootImage;
69 case 3: return OatFileAssistant::kDex2OatForFilter;
Vladimir Markoe0669322018-09-03 15:44:54 +010070 case 4: return -OatFileAssistant::kDex2OatForBootImage;
71 case 5: return -OatFileAssistant::kDex2OatForFilter;
Calin Juravle36eb3132017-01-13 16:32:38 -080072 default: return dexoptanalyzerResult;
73 }
74 }
75
76 // Verify that the output of dexoptanalyzer for the given arguments is the same
77 // as the output of OatFileAssistant::GetDexOptNeeded.
78 void Verify(const std::string& dex_file,
79 CompilerFilter::Filter compiler_filter,
Shubham Ajmerae4e812a2017-05-25 20:09:58 -070080 bool assume_profile_changed = false,
Nicolas Geoffray35de14b2019-01-10 13:10:36 +000081 bool downgrade = false,
82 const std::string& class_loader_context = "") {
83 int dexoptanalyzerResult = Analyze(
84 dex_file, compiler_filter, assume_profile_changed, class_loader_context);
Calin Juravle36eb3132017-01-13 16:32:38 -080085 dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
Andreas Gampe9b031f72018-10-04 11:03:34 -070086 OatFileAssistant oat_file_assistant(dex_file.c_str(), kRuntimeISA, /*load_executable=*/ false);
Calin Juravle36eb3132017-01-13 16:32:38 -080087 int assistantResult = oat_file_assistant.GetDexOptNeeded(
Shubham Ajmerae4e812a2017-05-25 20:09:58 -070088 compiler_filter, assume_profile_changed, downgrade);
Calin Juravle36eb3132017-01-13 16:32:38 -080089 EXPECT_EQ(assistantResult, dexoptanalyzerResult);
90 }
91};
92
93// The tests below exercise the same test case from oat_file_assistant_test.cc.
94
95// Case: We have a DEX file, but no OAT file for it.
96TEST_F(DexoptAnalyzerTest, DexNoOat) {
97 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
98 Copy(GetDexSrc1(), dex_location);
99
100 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100101 Verify(dex_location, CompilerFilter::kExtract);
102 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800103 Verify(dex_location, CompilerFilter::kSpeedProfile);
104}
105
106// Case: We have a DEX file and up-to-date OAT file for it.
107TEST_F(DexoptAnalyzerTest, OatUpToDate) {
108 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
109 Copy(GetDexSrc1(), dex_location);
110 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
111
112 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100113 Verify(dex_location, CompilerFilter::kQuicken);
114 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800115 Verify(dex_location, CompilerFilter::kEverything);
116}
117
118// Case: We have a DEX file and speed-profile OAT file for it.
119TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) {
120 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
121 Copy(GetDexSrc1(), dex_location);
122 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
123
124 Verify(dex_location, CompilerFilter::kSpeedProfile, false);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100125 Verify(dex_location, CompilerFilter::kQuicken, false);
Calin Juravle36eb3132017-01-13 16:32:38 -0800126 Verify(dex_location, CompilerFilter::kSpeedProfile, true);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100127 Verify(dex_location, CompilerFilter::kQuicken, true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800128}
129
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700130TEST_F(DexoptAnalyzerTest, Downgrade) {
131 std::string dex_location = GetScratchDir() + "/Downgrade.jar";
132 Copy(GetDexSrc1(), dex_location);
133 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
134
135 Verify(dex_location, CompilerFilter::kSpeedProfile, false, true);
136 Verify(dex_location, CompilerFilter::kQuicken, false, true);
137 Verify(dex_location, CompilerFilter::kVerify, false, true);
138}
139
Calin Juravle36eb3132017-01-13 16:32:38 -0800140// Case: We have a MultiDEX file and up-to-date OAT file for it.
141TEST_F(DexoptAnalyzerTest, MultiDexOatUpToDate) {
142 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
143 Copy(GetMultiDexSrc1(), dex_location);
144 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
145
146 Verify(dex_location, CompilerFilter::kSpeed, false);
147}
148
149// Case: We have a MultiDEX file where the secondary dex file is out of date.
150TEST_F(DexoptAnalyzerTest, MultiDexSecondaryOutOfDate) {
151 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
152
153 // Compile code for GetMultiDexSrc1.
154 Copy(GetMultiDexSrc1(), dex_location);
155 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
156
157 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
158 // is out of date.
159 Copy(GetMultiDexSrc2(), dex_location);
160
161 Verify(dex_location, CompilerFilter::kSpeed, false);
162}
163
164
165// Case: We have a DEX file and an OAT file out of date with respect to the
166// dex checksum.
167TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) {
168 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
169
170 // We create a dex, generate an oat for it, then overwrite the dex with a
171 // different dex to make the oat out of date.
172 Copy(GetDexSrc1(), dex_location);
173 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
174 Copy(GetDexSrc2(), dex_location);
175
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100176 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800177 Verify(dex_location, CompilerFilter::kSpeed);
178}
179
180// Case: We have a DEX file and an OAT file out of date with respect to the
181// boot image.
182TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) {
183 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
184
185 Copy(GetDexSrc1(), dex_location);
186 GenerateOatForTest(dex_location.c_str(),
187 CompilerFilter::kSpeed,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700188 /*with_alternate_image=*/true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800189
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100190 Verify(dex_location, CompilerFilter::kExtract);
191 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800192 Verify(dex_location, CompilerFilter::kSpeed);
193}
194
195// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
196// respect to the boot image.
197// It shouldn't matter that the OAT file is out of date, because it is
198// verify-at-runtime.
199TEST_F(DexoptAnalyzerTest, OatVerifyAtRuntimeImageOutOfDate) {
200 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
201
202 Copy(GetDexSrc1(), dex_location);
203 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100204 CompilerFilter::kExtract,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700205 /*with_alternate_image=*/true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800206
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100207 Verify(dex_location, CompilerFilter::kExtract);
208 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800209}
210
211// Case: We have a DEX file and an ODEX file, but no OAT file.
212TEST_F(DexoptAnalyzerTest, DexOdexNoOat) {
213 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
214 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
215
216 Copy(GetDexSrc1(), dex_location);
217 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
218
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100219 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800220 Verify(dex_location, CompilerFilter::kSpeed);
Vladimir Markoa2da9b92018-10-10 14:21:55 +0100221 Verify(dex_location, CompilerFilter::kEverything);
Calin Juravle36eb3132017-01-13 16:32:38 -0800222}
223
224// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
225TEST_F(DexoptAnalyzerTest, StrippedDexOdexNoOat) {
226 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
227 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
228
229 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100230 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle36eb3132017-01-13 16:32:38 -0800231
232 // Strip the dex file
233 Copy(GetStrippedDexSrc1(), dex_location);
234
235 Verify(dex_location, CompilerFilter::kSpeed);
236}
237
238// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
239TEST_F(DexoptAnalyzerTest, StrippedDexOdexOat) {
240 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
241 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
242
243 // Create the oat file from a different dex file so it looks out of date.
244 Copy(GetDexSrc2(), dex_location);
245 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
246
247 // Create the odex file
248 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100249 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle36eb3132017-01-13 16:32:38 -0800250
251 // Strip the dex file.
252 Copy(GetStrippedDexSrc1(), dex_location);
253
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100254 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800255 Verify(dex_location, CompilerFilter::kSpeed);
256 Verify(dex_location, CompilerFilter::kEverything);
257}
258
259// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
260// OAT file. Expect: The status is kNoDexOptNeeded.
261TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) {
262 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
263
264 Copy(GetStrippedDexSrc1(), dex_location);
265
266 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100267 Verify(dex_location, CompilerFilter::kExtract);
268 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800269}
270
Vladimir Markoe0669322018-09-03 15:44:54 +0100271// Case: We have a DEX file, an ODEX file and an OAT file.
Calin Juravle36eb3132017-01-13 16:32:38 -0800272TEST_F(DexoptAnalyzerTest, OdexOatOverlap) {
273 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
274 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
275 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
276
277 Copy(GetDexSrc1(), dex_location);
278 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
279
280 // Create the oat file by copying the odex so they are located in the same
281 // place in memory.
282 Copy(odex_location, oat_location);
283
284 Verify(dex_location, CompilerFilter::kSpeed);
285}
286
Calin Juravle36eb3132017-01-13 16:32:38 -0800287// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file..
288TEST_F(DexoptAnalyzerTest, DexVerifyAtRuntimeOdexNoOat) {
289 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
290 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
291
292 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100293 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800294
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100295 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800296 Verify(dex_location, CompilerFilter::kSpeed);
297}
298
299// Case: Non-standard extension for dex file.
300TEST_F(DexoptAnalyzerTest, LongDexExtension) {
301 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
302 Copy(GetDexSrc1(), dex_location);
303
304 Verify(dex_location, CompilerFilter::kSpeed);
305}
306
307// Case: Very short, non-existent Dex location.
308TEST_F(DexoptAnalyzerTest, ShortDexLocation) {
309 std::string dex_location = "/xx";
310
311 Verify(dex_location, CompilerFilter::kSpeed);
312}
313
Nicolas Geoffray35de14b2019-01-10 13:10:36 +0000314// Case: We have a DEX file and up-to-date OAT file for it, and we check with
315// a class loader context.
316TEST_F(DexoptAnalyzerTest, ClassLoaderContext) {
317 std::string dex_location1 = GetScratchDir() + "/DexToAnalyze.jar";
318 std::string odex_location1 = GetOdexDir() + "/DexToAnalyze.odex";
319 std::string dex_location2 = GetScratchDir() + "/DexInContext.jar";
320 Copy(GetDexSrc1(), dex_location1);
321 Copy(GetDexSrc2(), dex_location2);
322
323 std::string class_loader_context = "PCL[" + dex_location2 + "]";
324 std::string class_loader_context_option = "--class-loader-context=PCL[" + dex_location2 + "]";
325
326 // Generate the odex to get the class loader context also open the dex files.
327 GenerateOdexForTest(dex_location1, odex_location1, CompilerFilter::kSpeed, /* compilation_reason= */ nullptr, /* extra_args= */ { class_loader_context_option });
328
329 Verify(dex_location1, CompilerFilter::kSpeed, false, false, class_loader_context);
330}
331
Calin Juravle36eb3132017-01-13 16:32:38 -0800332} // namespace art