blob: ef6282aa1f8c2f7e4782d4a4b81082303c61ff6a [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"
Eric Holkc7ac91b2021-02-04 21:44:01 +000020#include "base/compiler_filter.h"
Calin Juravle36eb3132017-01-13 16:32:38 -080021#include "dexopt_test.h"
22
23namespace art {
24
25class DexoptAnalyzerTest : public DexoptTest {
26 protected:
27 std::string GetDexoptAnalyzerCmd() {
Martin Stjernholme58624f2019-09-20 15:53:40 +010028 std::string file_path = GetArtBinDir() + "/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,
Calin Juravle0a5cad32020-02-14 20:29:26 +000039 const char* 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_);
Calin Juravle0a5cad32020-02-14 20:29:26 +000055 if (class_loader_context != nullptr) {
56 argv_str.push_back("--class-loader-context=" + std::string(class_loader_context));
Nicolas Geoffray35de14b2019-01-10 13:10:36 +000057 }
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,
Calin Juravle0a5cad32020-02-14 20:29:26 +000081 const char* class_loader_context = "PCL[]") {
David Srbecky656fdcd2021-04-17 16:47:01 +000082 std::unique_ptr<ClassLoaderContext> context = class_loader_context == nullptr
83 ? nullptr
84 : ClassLoaderContext::Create(class_loader_context);
Nicolas Geoffray525fa422021-04-19 07:50:35 +000085 if (context != nullptr) {
86 std::vector<int> context_fds;
87 ASSERT_TRUE(context->OpenDexFiles("", context_fds, /*only_read_checksums*/ true));
88 }
David Srbecky656fdcd2021-04-17 16:47:01 +000089
Nicolas Geoffray525fa422021-04-19 07:50:35 +000090 int dexoptanalyzerResult = Analyze(
91 dex_file, compiler_filter, assume_profile_changed, class_loader_context);
92 dexoptanalyzerResult = DexoptanalyzerToOatFileAssistant(dexoptanalyzerResult);
93 OatFileAssistant oat_file_assistant(dex_file.c_str(),
94 kRuntimeISA,
95 context.get(),
96 /*load_executable=*/ false);
Calin Juravle36eb3132017-01-13 16:32:38 -080097 int assistantResult = oat_file_assistant.GetDexOptNeeded(
Nicolas Geoffray525fa422021-04-19 07:50:35 +000098 compiler_filter, assume_profile_changed, downgrade);
Calin Juravle36eb3132017-01-13 16:32:38 -080099 EXPECT_EQ(assistantResult, dexoptanalyzerResult);
100 }
101};
102
103// The tests below exercise the same test case from oat_file_assistant_test.cc.
104
105// Case: We have a DEX file, but no OAT file for it.
106TEST_F(DexoptAnalyzerTest, DexNoOat) {
107 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
108 Copy(GetDexSrc1(), dex_location);
109
110 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100111 Verify(dex_location, CompilerFilter::kExtract);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000112 Verify(dex_location, CompilerFilter::kVerify);
Calin Juravle36eb3132017-01-13 16:32:38 -0800113 Verify(dex_location, CompilerFilter::kSpeedProfile);
Calin Juravle0a5cad32020-02-14 20:29:26 +0000114 Verify(dex_location, CompilerFilter::kSpeed, false, false, nullptr);
Calin Juravle36eb3132017-01-13 16:32:38 -0800115}
116
117// Case: We have a DEX file and up-to-date OAT file for it.
118TEST_F(DexoptAnalyzerTest, OatUpToDate) {
119 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
120 Copy(GetDexSrc1(), dex_location);
121 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
122
123 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000124 Verify(dex_location, CompilerFilter::kVerify);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100125 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800126 Verify(dex_location, CompilerFilter::kEverything);
Calin Juravle0a5cad32020-02-14 20:29:26 +0000127 Verify(dex_location, CompilerFilter::kSpeed, false, false, nullptr);
Calin Juravle36eb3132017-01-13 16:32:38 -0800128}
129
130// Case: We have a DEX file and speed-profile OAT file for it.
131TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) {
132 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
133 Copy(GetDexSrc1(), dex_location);
134 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
135
136 Verify(dex_location, CompilerFilter::kSpeedProfile, false);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000137 Verify(dex_location, CompilerFilter::kVerify, false);
Calin Juravle36eb3132017-01-13 16:32:38 -0800138 Verify(dex_location, CompilerFilter::kSpeedProfile, true);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000139 Verify(dex_location, CompilerFilter::kVerify, true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800140}
141
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700142TEST_F(DexoptAnalyzerTest, Downgrade) {
143 std::string dex_location = GetScratchDir() + "/Downgrade.jar";
144 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000145 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kVerify);
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700146
147 Verify(dex_location, CompilerFilter::kSpeedProfile, false, true);
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700148 Verify(dex_location, CompilerFilter::kVerify, false, true);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000149 Verify(dex_location, CompilerFilter::kExtract, false, true);
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700150}
151
Calin Juravle36eb3132017-01-13 16:32:38 -0800152// Case: We have a MultiDEX file and up-to-date OAT file for it.
153TEST_F(DexoptAnalyzerTest, MultiDexOatUpToDate) {
154 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
155 Copy(GetMultiDexSrc1(), dex_location);
156 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
157
158 Verify(dex_location, CompilerFilter::kSpeed, false);
159}
160
161// Case: We have a MultiDEX file where the secondary dex file is out of date.
162TEST_F(DexoptAnalyzerTest, MultiDexSecondaryOutOfDate) {
163 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
164
165 // Compile code for GetMultiDexSrc1.
166 Copy(GetMultiDexSrc1(), dex_location);
167 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
168
169 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
170 // is out of date.
171 Copy(GetMultiDexSrc2(), dex_location);
172
173 Verify(dex_location, CompilerFilter::kSpeed, false);
174}
175
176
177// Case: We have a DEX file and an OAT file out of date with respect to the
178// dex checksum.
179TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) {
180 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
181
182 // We create a dex, generate an oat for it, then overwrite the dex with a
183 // different dex to make the oat out of date.
184 Copy(GetDexSrc1(), dex_location);
185 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
186 Copy(GetDexSrc2(), dex_location);
187
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100188 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800189 Verify(dex_location, CompilerFilter::kSpeed);
190}
191
192// Case: We have a DEX file and an OAT file out of date with respect to the
193// boot image.
194TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) {
195 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
196
197 Copy(GetDexSrc1(), dex_location);
198 GenerateOatForTest(dex_location.c_str(),
199 CompilerFilter::kSpeed,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700200 /*with_alternate_image=*/true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800201
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100202 Verify(dex_location, CompilerFilter::kExtract);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000203 Verify(dex_location, CompilerFilter::kVerify);
Calin Juravle36eb3132017-01-13 16:32:38 -0800204 Verify(dex_location, CompilerFilter::kSpeed);
205}
206
207// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
208// respect to the boot image.
209// It shouldn't matter that the OAT file is out of date, because it is
210// verify-at-runtime.
211TEST_F(DexoptAnalyzerTest, OatVerifyAtRuntimeImageOutOfDate) {
212 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
213
214 Copy(GetDexSrc1(), dex_location);
215 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100216 CompilerFilter::kExtract,
Andreas Gampe9b031f72018-10-04 11:03:34 -0700217 /*with_alternate_image=*/true);
Calin Juravle36eb3132017-01-13 16:32:38 -0800218
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100219 Verify(dex_location, CompilerFilter::kExtract);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000220 Verify(dex_location, CompilerFilter::kVerify);
Calin Juravle36eb3132017-01-13 16:32:38 -0800221}
222
223// Case: We have a DEX file and an ODEX file, but no OAT file.
224TEST_F(DexoptAnalyzerTest, DexOdexNoOat) {
225 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
226 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
227
228 Copy(GetDexSrc1(), dex_location);
229 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
230
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100231 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800232 Verify(dex_location, CompilerFilter::kSpeed);
Vladimir Markoa2da9b92018-10-10 14:21:55 +0100233 Verify(dex_location, CompilerFilter::kEverything);
Calin Juravle36eb3132017-01-13 16:32:38 -0800234}
235
Calin Juravle36eb3132017-01-13 16:32:38 -0800236// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
237// OAT file. Expect: The status is kNoDexOptNeeded.
238TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) {
239 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
240
Calin Juravle5ff23932020-12-11 18:26:14 -0800241 Copy(GetResourceOnlySrc1(), dex_location);
Calin Juravle36eb3132017-01-13 16:32:38 -0800242
243 Verify(dex_location, CompilerFilter::kSpeed);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100244 Verify(dex_location, CompilerFilter::kExtract);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000245 Verify(dex_location, CompilerFilter::kVerify);
Calin Juravle36eb3132017-01-13 16:32:38 -0800246}
247
Vladimir Markoe0669322018-09-03 15:44:54 +0100248// Case: We have a DEX file, an ODEX file and an OAT file.
Calin Juravle36eb3132017-01-13 16:32:38 -0800249TEST_F(DexoptAnalyzerTest, OdexOatOverlap) {
250 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
251 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
252 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
253
254 Copy(GetDexSrc1(), dex_location);
255 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
256
257 // Create the oat file by copying the odex so they are located in the same
258 // place in memory.
259 Copy(odex_location, oat_location);
260
261 Verify(dex_location, CompilerFilter::kSpeed);
262}
263
Calin Juravle36eb3132017-01-13 16:32:38 -0800264// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file..
265TEST_F(DexoptAnalyzerTest, DexVerifyAtRuntimeOdexNoOat) {
266 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
267 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
268
269 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100270 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800271
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100272 Verify(dex_location, CompilerFilter::kExtract);
Calin Juravle36eb3132017-01-13 16:32:38 -0800273 Verify(dex_location, CompilerFilter::kSpeed);
274}
275
276// Case: Non-standard extension for dex file.
277TEST_F(DexoptAnalyzerTest, LongDexExtension) {
278 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
279 Copy(GetDexSrc1(), dex_location);
280
281 Verify(dex_location, CompilerFilter::kSpeed);
282}
283
284// Case: Very short, non-existent Dex location.
285TEST_F(DexoptAnalyzerTest, ShortDexLocation) {
286 std::string dex_location = "/xx";
287
288 Verify(dex_location, CompilerFilter::kSpeed);
289}
290
Nicolas Geoffray35de14b2019-01-10 13:10:36 +0000291// Case: We have a DEX file and up-to-date OAT file for it, and we check with
292// a class loader context.
293TEST_F(DexoptAnalyzerTest, ClassLoaderContext) {
294 std::string dex_location1 = GetScratchDir() + "/DexToAnalyze.jar";
295 std::string odex_location1 = GetOdexDir() + "/DexToAnalyze.odex";
296 std::string dex_location2 = GetScratchDir() + "/DexInContext.jar";
297 Copy(GetDexSrc1(), dex_location1);
298 Copy(GetDexSrc2(), dex_location2);
299
300 std::string class_loader_context = "PCL[" + dex_location2 + "]";
301 std::string class_loader_context_option = "--class-loader-context=PCL[" + dex_location2 + "]";
302
303 // Generate the odex to get the class loader context also open the dex files.
304 GenerateOdexForTest(dex_location1, odex_location1, CompilerFilter::kSpeed, /* compilation_reason= */ nullptr, /* extra_args= */ { class_loader_context_option });
305
Calin Juravle0a5cad32020-02-14 20:29:26 +0000306 Verify(dex_location1, CompilerFilter::kSpeed, false, false, class_loader_context.c_str());
Nicolas Geoffray35de14b2019-01-10 13:10:36 +0000307}
Calin Juravle36eb3132017-01-13 16:32:38 -0800308} // namespace art