blob: 1cbf5461a494c84af3483f3fb226539dd38a8edf [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,
Shubham Ajmerae4e812a2017-05-25 20:09:58 -070074 bool assume_profile_changed = false,
75 bool downgrade = false) {
Calin Juravle36eb3132017-01-13 16:32:38 -080076 int dexoptanalyzerResult = Analyze(dex_file, compiler_filter, assume_profile_changed);
77 dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
78 OatFileAssistant oat_file_assistant(dex_file.c_str(), kRuntimeISA, /*load_executable*/ false);
79 int assistantResult = oat_file_assistant.GetDexOptNeeded(
Shubham Ajmerae4e812a2017-05-25 20:09:58 -070080 compiler_filter, assume_profile_changed, downgrade);
Calin Juravle36eb3132017-01-13 16:32:38 -080081 EXPECT_EQ(assistantResult, dexoptanalyzerResult);
82 }
83};
84
85// The tests below exercise the same test case from oat_file_assistant_test.cc.
86
87// Case: We have a DEX file, but no OAT file for it.
88TEST_F(DexoptAnalyzerTest, DexNoOat) {
89 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
90 Copy(GetDexSrc1(), dex_location);
91
92 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +010093 Verify(dex_location, CompilerFilter::kExtract);
94 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -080095 Verify(dex_location, CompilerFilter::kSpeedProfile);
96}
97
98// Case: We have a DEX file and up-to-date OAT file for it.
99TEST_F(DexoptAnalyzerTest, OatUpToDate) {
100 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
101 Copy(GetDexSrc1(), dex_location);
102 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
103
104 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100105 Verify(dex_location, CompilerFilter::kQuicken);
106 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800107 Verify(dex_location, CompilerFilter::kEverything);
108}
109
110// Case: We have a DEX file and speed-profile OAT file for it.
111TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) {
112 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
113 Copy(GetDexSrc1(), dex_location);
114 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
115
116 Verify(dex_location, CompilerFilter::kSpeedProfile, false);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100117 Verify(dex_location, CompilerFilter::kQuicken, false);
Calin Juravle36eb3132017-01-13 16:32:38 -0800118 Verify(dex_location, CompilerFilter::kSpeedProfile, true);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100119 Verify(dex_location, CompilerFilter::kQuicken, true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800120}
121
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700122TEST_F(DexoptAnalyzerTest, Downgrade) {
123 std::string dex_location = GetScratchDir() + "/Downgrade.jar";
124 Copy(GetDexSrc1(), dex_location);
125 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
126
127 Verify(dex_location, CompilerFilter::kSpeedProfile, false, true);
128 Verify(dex_location, CompilerFilter::kQuicken, false, true);
129 Verify(dex_location, CompilerFilter::kVerify, false, true);
130}
131
Calin Juravle36eb3132017-01-13 16:32:38 -0800132// Case: We have a MultiDEX file and up-to-date OAT file for it.
133TEST_F(DexoptAnalyzerTest, MultiDexOatUpToDate) {
134 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
135 Copy(GetMultiDexSrc1(), dex_location);
136 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
137
138 Verify(dex_location, CompilerFilter::kSpeed, false);
139}
140
141// Case: We have a MultiDEX file where the secondary dex file is out of date.
142TEST_F(DexoptAnalyzerTest, MultiDexSecondaryOutOfDate) {
143 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
144
145 // Compile code for GetMultiDexSrc1.
146 Copy(GetMultiDexSrc1(), dex_location);
147 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
148
149 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
150 // is out of date.
151 Copy(GetMultiDexSrc2(), dex_location);
152
153 Verify(dex_location, CompilerFilter::kSpeed, false);
154}
155
156
157// Case: We have a DEX file and an OAT file out of date with respect to the
158// dex checksum.
159TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) {
160 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
161
162 // We create a dex, generate an oat for it, then overwrite the dex with a
163 // different dex to make the oat out of date.
164 Copy(GetDexSrc1(), dex_location);
165 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
166 Copy(GetDexSrc2(), dex_location);
167
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100168 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800169 Verify(dex_location, CompilerFilter::kSpeed);
170}
171
172// Case: We have a DEX file and an OAT file out of date with respect to the
173// boot image.
174TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) {
175 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
176
177 Copy(GetDexSrc1(), dex_location);
178 GenerateOatForTest(dex_location.c_str(),
179 CompilerFilter::kSpeed,
180 /*relocate*/true,
181 /*pic*/false,
182 /*with_alternate_image*/true);
183
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100184 Verify(dex_location, CompilerFilter::kExtract);
185 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800186 Verify(dex_location, CompilerFilter::kSpeed);
187}
188
189// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
190// respect to the boot image.
191// It shouldn't matter that the OAT file is out of date, because it is
192// verify-at-runtime.
193TEST_F(DexoptAnalyzerTest, OatVerifyAtRuntimeImageOutOfDate) {
194 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
195
196 Copy(GetDexSrc1(), dex_location);
197 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100198 CompilerFilter::kExtract,
Calin Juravle36eb3132017-01-13 16:32:38 -0800199 /*relocate*/true,
200 /*pic*/false,
201 /*with_alternate_image*/true);
202
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100203 Verify(dex_location, CompilerFilter::kExtract);
204 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800205}
206
207// Case: We have a DEX file and an ODEX file, but no OAT file.
208TEST_F(DexoptAnalyzerTest, DexOdexNoOat) {
209 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
210 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
211
212 Copy(GetDexSrc1(), dex_location);
213 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
214
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100215 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800216 Verify(dex_location, CompilerFilter::kSpeed);
217}
218
219// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
220TEST_F(DexoptAnalyzerTest, StrippedDexOdexNoOat) {
221 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
222 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
223
224 Copy(GetDexSrc1(), dex_location);
225 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
226
227 // Strip the dex file
228 Copy(GetStrippedDexSrc1(), dex_location);
229
230 Verify(dex_location, CompilerFilter::kSpeed);
231}
232
233// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
234TEST_F(DexoptAnalyzerTest, StrippedDexOdexOat) {
235 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
236 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
237
238 // Create the oat file from a different dex file so it looks out of date.
239 Copy(GetDexSrc2(), dex_location);
240 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
241
242 // Create the odex file
243 Copy(GetDexSrc1(), dex_location);
244 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
245
246 // Strip the dex file.
247 Copy(GetStrippedDexSrc1(), dex_location);
248
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100249 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800250 Verify(dex_location, CompilerFilter::kSpeed);
251 Verify(dex_location, CompilerFilter::kEverything);
252}
253
254// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
255// OAT file. Expect: The status is kNoDexOptNeeded.
256TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) {
257 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
258
259 Copy(GetStrippedDexSrc1(), dex_location);
260
261 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100262 Verify(dex_location, CompilerFilter::kExtract);
263 Verify(dex_location, CompilerFilter::kQuicken);
Calin Juravle36eb3132017-01-13 16:32:38 -0800264}
265
266// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
267// OAT files both have patch delta of 0.
268TEST_F(DexoptAnalyzerTest, OdexOatOverlap) {
269 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
270 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
271 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
272
273 Copy(GetDexSrc1(), dex_location);
274 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
275
276 // Create the oat file by copying the odex so they are located in the same
277 // place in memory.
278 Copy(odex_location, oat_location);
279
280 Verify(dex_location, CompilerFilter::kSpeed);
281}
282
283// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
284TEST_F(DexoptAnalyzerTest, DexPicOdexNoOat) {
285 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
286 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex";
287
288 Copy(GetDexSrc1(), dex_location);
289 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
290
291 Verify(dex_location, CompilerFilter::kSpeed);
292 Verify(dex_location, CompilerFilter::kEverything);
293}
294
295// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file..
296TEST_F(DexoptAnalyzerTest, DexVerifyAtRuntimeOdexNoOat) {
297 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
298 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
299
300 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100301 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800302
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100303 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800304 Verify(dex_location, CompilerFilter::kSpeed);
305}
306
307// Case: Non-standard extension for dex file.
308TEST_F(DexoptAnalyzerTest, LongDexExtension) {
309 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
310 Copy(GetDexSrc1(), dex_location);
311
312 Verify(dex_location, CompilerFilter::kSpeed);
313}
314
315// Case: Very short, non-existent Dex location.
316TEST_F(DexoptAnalyzerTest, ShortDexLocation) {
317 std::string dex_location = "/xx";
318
319 Verify(dex_location, CompilerFilter::kSpeed);
320}
321
322} // namespace art