blob: 376088568ab4257db46c72d67836061ad0666df8 [file] [log] [blame]
Richard Uhler66d874d2015-01-15 09:37:19 -08001/*
2 * Copyright (C) 2014 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
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070017#include "oat_file_assistant.h"
18
Richard Uhler66d874d2015-01-15 09:37:19 -080019#include <sys/param.h>
20
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070021#include <string>
22#include <vector>
Shubham Ajmerab22dea02017-10-04 18:36:41 -070023#include <fcntl.h>
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070024
Richard Uhler66d874d2015-01-15 09:37:19 -080025#include <gtest/gtest.h>
26
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070027#include "android-base/strings.h"
28
Mathieu Chartierc7853442015-03-27 14:35:38 -070029#include "art_field-inl.h"
David Sehrc431b9d2018-03-02 12:01:51 -080030#include "base/os.h"
31#include "base/utils.h"
Vladimir Marko3481ba22015-04-13 12:22:36 +010032#include "class_linker-inl.h"
Calin Juravle27e0d1f2017-07-26 00:16:07 -070033#include "class_loader_context.h"
Jeff Hao0cb17282017-07-12 14:51:49 -070034#include "common_runtime_test.h"
Calin Juravle36eb3132017-01-13 16:32:38 -080035#include "dexopt_test.h"
David Brazdil32bde992018-05-14 15:24:34 +010036#include "hidden_api.h"
Vladimir Markod3d00c02019-11-07 15:09:07 +000037#include "oat.h"
Calin Juravle27e0d1f2017-07-26 00:16:07 -070038#include "oat_file.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070039#include "oat_file_manager.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070040#include "scoped_thread_state_change-inl.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070041#include "thread-current-inl.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080042
43namespace art {
44
Calin Juravle5f9a8012018-02-12 20:27:46 -080045class OatFileAssistantTest : public DexoptTest {
46 public:
Calin Juravle98071152021-01-27 18:41:58 -080047 void VerifyOptimizationStatus(OatFileAssistant* assistant,
48 const std::string& file,
Calin Juravle5f9a8012018-02-12 20:27:46 -080049 const std::string& expected_filter,
Calin Juravle98071152021-01-27 18:41:58 -080050 const std::string& expected_reason,
51 const std::string& expected_odex_status) {
52 // Verify the static methods (called from PM for dexOptNeeded).
53 std::string compilation_filter1;
54 std::string compilation_reason1;
Calin Juravle5f9a8012018-02-12 20:27:46 -080055
Calin Juravle98071152021-01-27 18:41:58 -080056 OatFileAssistant::GetOptimizationStatus(
57 file, kRuntimeISA, &compilation_filter1, &compilation_reason1);
58
59 ASSERT_EQ(expected_filter, compilation_filter1);
60 ASSERT_EQ(expected_reason, compilation_reason1);
61
62 // Verify the instance methods (called at runtime for systrace).
63 std::string odex_location2; // ignored
64 std::string compilation_filter2;
65 std::string compilation_reason2;
66 std::string odex_status2;
67
68 assistant->GetOptimizationStatus(
69 &odex_location2,
70 &compilation_filter2,
71 &compilation_reason2,
72 &odex_status2);
73
74 ASSERT_EQ(expected_filter, compilation_filter2);
75 ASSERT_EQ(expected_reason, compilation_reason2);
76 ASSERT_EQ(expected_odex_status, odex_status2);
Calin Juravle5f9a8012018-02-12 20:27:46 -080077 }
78
Calin Juravle98071152021-01-27 18:41:58 -080079 void VerifyOptimizationStatus(OatFileAssistant* assistant,
80 const std::string& file,
Calin Juravle5f9a8012018-02-12 20:27:46 -080081 CompilerFilter::Filter expected_filter,
Calin Juravle98071152021-01-27 18:41:58 -080082 const std::string& expected_reason,
83 const std::string& expected_odex_status) {
Calin Juravle5f9a8012018-02-12 20:27:46 -080084 VerifyOptimizationStatus(
Calin Juravle98071152021-01-27 18:41:58 -080085 assistant,
86 file,
87 CompilerFilter::NameOfFilter(expected_filter),
88 expected_reason,
89 expected_odex_status);
Calin Juravle5f9a8012018-02-12 20:27:46 -080090 }
Calin Juravle0a5cad32020-02-14 20:29:26 +000091
Vladimir Markof3d88a82018-12-21 16:38:47 +000092 void InsertNewBootClasspathEntry() {
93 std::string extra_dex_filename = GetMultiDexSrc1();
94 Runtime* runtime = Runtime::Current();
95 runtime->boot_class_path_.push_back(extra_dex_filename);
96 if (!runtime->boot_class_path_locations_.empty()) {
97 runtime->boot_class_path_locations_.push_back(extra_dex_filename);
98 }
99 }
Calin Juravle0a5cad32020-02-14 20:29:26 +0000100
Calin Juravle0a5cad32020-02-14 20:29:26 +0000101 int GetDexOptNeeded(
102 OatFileAssistant* assistant,
103 CompilerFilter::Filter compiler_filter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000104 bool profile_changed = false,
105 bool downgrade = false) {
106 return assistant->GetDexOptNeeded(
107 compiler_filter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000108 profile_changed,
109 downgrade);
110 }
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000111
112 static std::unique_ptr<ClassLoaderContext> InitializeDefaultContext() {
113 auto context = ClassLoaderContext::Default();
114 context->OpenDexFiles();
115 return context;
116 }
117
118 std::unique_ptr<ClassLoaderContext> default_context_ = InitializeDefaultContext();
Calin Juravle5f9a8012018-02-12 20:27:46 -0800119};
Richard Uhler66d874d2015-01-15 09:37:19 -0800120
Calin Juravle357c66d2017-05-04 01:57:17 +0000121class ScopedNonWritable {
122 public:
123 explicit ScopedNonWritable(const std::string& dex_location) {
124 is_valid_ = false;
125 size_t pos = dex_location.rfind('/');
126 if (pos != std::string::npos) {
127 is_valid_ = true;
128 dex_parent_ = dex_location.substr(0, pos);
129 if (chmod(dex_parent_.c_str(), 0555) != 0) {
130 PLOG(ERROR) << "Could not change permissions on " << dex_parent_;
131 }
132 }
133 }
134
135 bool IsSuccessful() { return is_valid_ && (access(dex_parent_.c_str(), W_OK) != 0); }
136
137 ~ScopedNonWritable() {
138 if (is_valid_) {
139 if (chmod(dex_parent_.c_str(), 0777) != 0) {
140 PLOG(ERROR) << "Could not restore permissions on " << dex_parent_;
141 }
142 }
143 }
144
145 private:
146 std::string dex_parent_;
147 bool is_valid_;
148};
149
150static bool IsExecutedAsRoot() {
151 return geteuid() == 0;
152}
Calin Juravle36eb3132017-01-13 16:32:38 -0800153
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000154// Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
155// encoded dex locations.
156// Expect: The oat file status is kNoDexOptNeeded.
157TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
158 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
159 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
160
161 // Create the dex file
162 Copy(GetMultiDexSrc1(), dex_location);
163
164 // Create the oat file with relative encoded dex location.
165 std::vector<std::string> args = {
166 "--dex-file=" + dex_location,
167 "--dex-location=" + std::string("RelativeEncodedDexLocation.jar"),
168 "--oat-file=" + odex_location,
169 "--compiler-filter=speed"
170 };
171
172 std::string error_msg;
173 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
174
175 // Verify we can load both dex files.
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000176 OatFileAssistant oat_file_assistant(dex_location.c_str(),
177 kRuntimeISA,
178 default_context_.get(),
179 true);
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000180
181 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
182 ASSERT_TRUE(oat_file.get() != nullptr);
183 EXPECT_TRUE(oat_file->IsExecutable());
184 std::vector<std::unique_ptr<const DexFile>> dex_files;
185 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
186 EXPECT_EQ(2u, dex_files.size());
187}
188
189TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
190 std::string dex_location = GetScratchDir() + "/TestDex.jar";
191 std::string odex_location = GetOdexDir() + "/TestDex.odex";
192 std::string context_location = GetScratchDir() + "/ContextDex.jar";
193 Copy(GetDexSrc1(), dex_location);
194 Copy(GetDexSrc2(), context_location);
195
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000196 std::string context_str = "PCL[" + context_location + "]";
197 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
198 ASSERT_TRUE(context != nullptr);
Calin Juravle5ff23932020-12-11 18:26:14 -0800199 ASSERT_TRUE(context->OpenDexFiles());
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000200
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000201 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, context.get(), false);
202
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000203 std::string error_msg;
204 std::vector<std::string> args;
205 args.push_back("--dex-file=" + dex_location);
206 args.push_back("--oat-file=" + odex_location);
207 args.push_back("--class-loader-context=" + context_str);
208 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
209
210 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000211 ASSERT_NE(nullptr, oat_file.get());
212 ASSERT_NE(nullptr, oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000213 EXPECT_EQ(context->EncodeContextForOatFile(""),
214 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
215}
216
217TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
218 std::string dex_location = GetScratchDir() + "/TestDex.jar";
219 std::string odex_location = GetOdexDir() + "/TestDex.odex";
220 std::string context_location = GetScratchDir() + "/ContextDex.jar";
221 Copy(GetDexSrc1(), dex_location);
222 Copy(GetDexSrc2(), context_location);
223
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000224 // A relative context simulates a dependent split context.
225 std::unique_ptr<ClassLoaderContext> relative_context =
226 ClassLoaderContext::Create("PCL[ContextDex.jar]");
227 ASSERT_TRUE(relative_context != nullptr);
228 std::vector<int> context_fds;
229 ASSERT_TRUE(relative_context->OpenDexFiles(GetScratchDir(), context_fds));
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000230
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000231 OatFileAssistant oat_file_assistant(dex_location.c_str(),
232 kRuntimeISA,
233 relative_context.get(),
234 false);
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000235
236 std::string error_msg;
237 std::vector<std::string> args;
238 args.push_back("--dex-file=" + dex_location);
239 args.push_back("--oat-file=" + odex_location);
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000240 args.push_back("--class-loader-context=PCL[" + context_location + "]");
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000241 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
242
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000243 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000244 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kDefaultCompilerFilter));
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000245}
246
Richard Uhler66d874d2015-01-15 09:37:19 -0800247// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700248// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800249TEST_F(OatFileAssistantTest, DexNoOat) {
250 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
251 Copy(GetDexSrc1(), dex_location);
252
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000253 OatFileAssistant oat_file_assistant(dex_location.c_str(),
254 kRuntimeISA,
255 default_context_.get(),
256 false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800257
Richard Uhler7225a8d2016-11-22 10:12:03 +0000258 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000259 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000260 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000261 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000262 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000263 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000264 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000265 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800266
267 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000268 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
269 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100270 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800271
Calin Juravle98071152021-01-27 18:41:58 -0800272 VerifyOptimizationStatus(
273 &oat_file_assistant,
274 dex_location,
275 "run-from-apk",
276 "unknown",
277 "io-error-no-oat");
Richard Uhler66d874d2015-01-15 09:37:19 -0800278}
279
280// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700281// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800282TEST_F(OatFileAssistantTest, NoDexNoOat) {
283 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
284
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000285 OatFileAssistant oat_file_assistant(dex_location.c_str(),
286 kRuntimeISA,
287 default_context_.get(),
288 true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800289
Andreas Gampe29d38e72016-03-23 15:31:51 +0000290 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000291 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100292 EXPECT_FALSE(oat_file_assistant.HasDexFiles());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700293
Richard Uhler9b994ea2015-06-24 08:44:19 -0700294 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800295 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
296 EXPECT_EQ(nullptr, oat_file.get());
297}
298
Vladimir Markoe0669322018-09-03 15:44:54 +0100299// Case: We have a DEX file and an ODEX file, but no OAT file.
300// Expect: The status is kNoDexOptNeeded.
Calin Juravle357c66d2017-05-04 01:57:17 +0000301TEST_F(OatFileAssistantTest, OdexUpToDate) {
302 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
303 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
304 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100305 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000306
Vladimir Markof3d88a82018-12-21 16:38:47 +0000307 // Force the use of oat location by making the dex parent not writable.
308 OatFileAssistant oat_file_assistant(
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000309 dex_location.c_str(),
310 kRuntimeISA,
311 default_context_.get(),
312 /*load_executable=*/ false);
Calin Juravle357c66d2017-05-04 01:57:17 +0000313
314 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000315 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Calin Juravle357c66d2017-05-04 01:57:17 +0000316 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000317 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Calin Juravle357c66d2017-05-04 01:57:17 +0000318 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000319 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Calin Juravle357c66d2017-05-04 01:57:17 +0000320 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000321 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
Vladimir Markof3d88a82018-12-21 16:38:47 +0000322
323 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
324 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
325 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100326 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Vladimir Markof3d88a82018-12-21 16:38:47 +0000327
Calin Juravle98071152021-01-27 18:41:58 -0800328 VerifyOptimizationStatus(
329 &oat_file_assistant,
330 dex_location,
331 CompilerFilter::kSpeed,
332 "install",
333 "up-to-date");
Vladimir Markof3d88a82018-12-21 16:38:47 +0000334}
335
336// Case: We have an ODEX file compiled against partial boot image.
337// Expect: The status is kNoDexOptNeeded.
338TEST_F(OatFileAssistantTest, OdexUpToDatePartialBootImage) {
339 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
340 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
341 Copy(GetDexSrc1(), dex_location);
342 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
343
344 // Insert an extra dex file to the boot class path.
345 InsertNewBootClasspathEntry();
346
347 // Force the use of oat location by making the dex parent not writable.
348 OatFileAssistant oat_file_assistant(
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000349 dex_location.c_str(),
350 kRuntimeISA,
351 default_context_.get(),
352 /*load_executable=*/ false);
Vladimir Markof3d88a82018-12-21 16:38:47 +0000353
354 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000355 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Vladimir Markof3d88a82018-12-21 16:38:47 +0000356 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000357 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Vladimir Markof3d88a82018-12-21 16:38:47 +0000358 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000359 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Vladimir Markof3d88a82018-12-21 16:38:47 +0000360 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000361 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
Calin Juravle357c66d2017-05-04 01:57:17 +0000362
363 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
364 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
365 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100366 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800367
Calin Juravle98071152021-01-27 18:41:58 -0800368 VerifyOptimizationStatus(
369 &oat_file_assistant,
370 dex_location,
371 CompilerFilter::kSpeed,
372 "install",
373 "up-to-date");
Calin Juravle357c66d2017-05-04 01:57:17 +0000374}
375
376// Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
377// file via a symlink.
Vladimir Markoe0669322018-09-03 15:44:54 +0100378// Expect: The status is kNoDexOptNeeded.
Calin Juravle357c66d2017-05-04 01:57:17 +0000379TEST_F(OatFileAssistantTest, OdexUpToDateSymLink) {
380 std::string scratch_dir = GetScratchDir();
381 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
382 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
383
384 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100385 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle357c66d2017-05-04 01:57:17 +0000386
387 // Now replace the dex location with a symlink.
388 std::string link = scratch_dir + "/link";
389 ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str()));
390 dex_location = link + "/OdexUpToDate.jar";
391
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000392 OatFileAssistant oat_file_assistant(dex_location.c_str(),
393 kRuntimeISA,
394 default_context_.get(),
395 false);
Calin Juravle357c66d2017-05-04 01:57:17 +0000396
397 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000398 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Calin Juravle357c66d2017-05-04 01:57:17 +0000399 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000400 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Calin Juravle357c66d2017-05-04 01:57:17 +0000401 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000402 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Calin Juravle357c66d2017-05-04 01:57:17 +0000403 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000404 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
Calin Juravle357c66d2017-05-04 01:57:17 +0000405
406 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
407 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
408 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100409 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Calin Juravle357c66d2017-05-04 01:57:17 +0000410}
411
Richard Uhler66d874d2015-01-15 09:37:19 -0800412// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700413// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800414TEST_F(OatFileAssistantTest, OatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000415 if (IsExecutedAsRoot()) {
416 // We cannot simulate non writable locations when executed as root: b/38000545.
417 LOG(ERROR) << "Test skipped because it's running as root";
418 return;
419 }
420
Richard Uhler66d874d2015-01-15 09:37:19 -0800421 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
422 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000423 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800424
Vladimir Markof3d88a82018-12-21 16:38:47 +0000425 // Force the use of oat location by making the dex parent not writable.
Calin Juravle357c66d2017-05-04 01:57:17 +0000426 ScopedNonWritable scoped_non_writable(dex_location);
427 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
428
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000429 OatFileAssistant oat_file_assistant(dex_location.c_str(),
430 kRuntimeISA,
431 default_context_.get(),
432 false);
Calin Juravle357c66d2017-05-04 01:57:17 +0000433
434 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000435 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Calin Juravle357c66d2017-05-04 01:57:17 +0000436 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000437 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Calin Juravle357c66d2017-05-04 01:57:17 +0000438 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000439 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Calin Juravle357c66d2017-05-04 01:57:17 +0000440 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000441 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
Calin Juravle357c66d2017-05-04 01:57:17 +0000442
443 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
444 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
445 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100446 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800447
Calin Juravle98071152021-01-27 18:41:58 -0800448 VerifyOptimizationStatus(
449 &oat_file_assistant,
450 dex_location,
451 CompilerFilter::kSpeed,
452 "unknown",
453 "up-to-date");
Calin Juravle357c66d2017-05-04 01:57:17 +0000454}
455
Vladimir Markoe0669322018-09-03 15:44:54 +0100456// Case: Passing valid file descriptors of updated odex/vdex files along with the dex file.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700457// Expect: The status is kNoDexOptNeeded.
458TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) {
459 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
460 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
461 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
462
463 Copy(GetDexSrc1(), dex_location);
464 GenerateOatForTest(dex_location.c_str(),
465 odex_location.c_str(),
466 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700467 /* with_alternate_image= */ false);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700468
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700469 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY | O_CLOEXEC));
470 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY | O_CLOEXEC));
471 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700472
473 OatFileAssistant oat_file_assistant(dex_location.c_str(),
474 kRuntimeISA,
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000475 default_context_.get(),
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700476 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000477 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700478 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700479 odex_fd.get(),
480 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700481 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000482 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700483 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000484 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700485 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000486 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700487 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000488 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700489
490 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
491 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
492 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100493 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700494}
495
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700496// Case: Passing invalid odex fd and valid vdex and zip fds.
497// Expect: The status should be kDex2OatForBootImage.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700498TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
499 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
500 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
501 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
502
503 Copy(GetDexSrc1(), dex_location);
504 GenerateOatForTest(dex_location.c_str(),
505 odex_location.c_str(),
506 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700507 /* with_alternate_image= */ false);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700508
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700509 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY | O_CLOEXEC));
510 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700511
512 OatFileAssistant oat_file_assistant(dex_location.c_str(),
513 kRuntimeISA,
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000514 default_context_.get(),
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700515 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000516 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700517 vdex_fd.get(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700518 /* oat_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700519 zip_fd.get());
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000520 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
521 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
522 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000523 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000524 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000525 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kEverything));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700526
527 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000528 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700529 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100530 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700531}
532
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700533// Case: Passing invalid vdex fd and valid odex and zip fds.
534// Expect: The status should be kDex2OatFromScratch.
535TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
536 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
537 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
538
539 Copy(GetDexSrc1(), dex_location);
540 GenerateOatForTest(dex_location.c_str(),
541 odex_location.c_str(),
542 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700543 /* with_alternate_image= */ false);
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700544
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700545 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY | O_CLOEXEC));
546 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700547
548 OatFileAssistant oat_file_assistant(dex_location.c_str(),
549 kRuntimeISA,
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000550 default_context_.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700551 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000552 false,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700553 /* vdex_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700554 odex_fd.get(),
555 zip_fd.get());
556
557 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000558 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700559 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
560 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
561 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100562 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700563}
564
565// Case: Passing invalid vdex and odex fd with valid zip fd.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700566// Expect: The status is kDex2oatFromScratch.
567TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
568 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
569
570 Copy(GetDexSrc1(), dex_location);
571
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700572 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700573 OatFileAssistant oat_file_assistant(dex_location.c_str(),
574 kRuntimeISA,
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000575 default_context_.get(),
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700576 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000577 false,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700578 /* vdex_fd= */ -1,
579 /* oat_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700580 zip_fd);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700581 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000582 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700583 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
584 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
585}
586
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000587// Case: We have a DEX file and up-to-date VDEX file for it, but no
Richard Uhler2f27abd2017-01-31 14:02:34 +0000588// ODEX file.
589TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000590 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000591 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000592
Richard Uhler9a37efc2016-08-05 16:32:55 -0700593 Copy(GetDexSrc1(), dex_location);
594
Richard Uhler2f27abd2017-01-31 14:02:34 +0000595 // Generating and deleting the oat file should have the side effect of
596 // creating an up-to-date vdex file.
Calin Juravle357c66d2017-05-04 01:57:17 +0000597 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
598 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000599
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000600 OatFileAssistant oat_file_assistant(dex_location.c_str(),
601 kRuntimeISA,
602 default_context_.get(),
603 false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000604
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000605 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
606 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
607 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000608 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000609
610 // Make sure we don't crash in this case when we dump the status. We don't
611 // care what the actual dumped value is.
612 oat_file_assistant.GetStatusDump();
Calin Juravle5f9a8012018-02-12 20:27:46 -0800613
Calin Juravle98071152021-01-27 18:41:58 -0800614 VerifyOptimizationStatus(
615 &oat_file_assistant,
616 dex_location,
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000617 "verify",
Calin Juravle98071152021-01-27 18:41:58 -0800618 "unknown",
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000619 "up-to-date");
Richard Uhler2f27abd2017-01-31 14:02:34 +0000620}
621
622// Case: We have a DEX file and empty VDEX and ODEX files.
623TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
624 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
625 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
626 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
627
628 Copy(GetDexSrc1(), dex_location);
Richard Uhler5cd59292017-02-01 12:54:23 +0000629 ScratchFile vdex_file(vdex_location.c_str());
630 ScratchFile odex_file(odex_location.c_str());
Richard Uhler2f27abd2017-01-31 14:02:34 +0000631
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000632 OatFileAssistant oat_file_assistant(dex_location.c_str(),
633 kRuntimeISA,
634 default_context_.get(),
635 false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000636 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000637 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000638}
639
640// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
641// file.
642TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000643 if (IsExecutedAsRoot()) {
644 // We cannot simulate non writable locations when executed as root: b/38000545.
645 LOG(ERROR) << "Test skipped because it's running as root";
646 return;
647 }
Richard Uhler2f27abd2017-01-31 14:02:34 +0000648
649 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
650 std::string oat_location;
651 std::string error_msg;
652 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
653 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
654
655 Copy(GetDexSrc1(), dex_location);
656 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
657 ASSERT_EQ(0, unlink(oat_location.c_str()));
658
Calin Juravle357c66d2017-05-04 01:57:17 +0000659 ScopedNonWritable scoped_non_writable(dex_location);
660 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000661 OatFileAssistant oat_file_assistant(dex_location.c_str(),
662 kRuntimeISA,
663 default_context_.get(),
664 false);
Richard Uhler9a37efc2016-08-05 16:32:55 -0700665
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000666 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000667 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700668}
669
Andreas Gampe29d38e72016-03-23 15:31:51 +0000670// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700671// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
672// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000673TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000674 if (IsExecutedAsRoot()) {
675 // We cannot simulate non writable locations when executed as root: b/38000545.
676 LOG(ERROR) << "Test skipped because it's running as root";
677 return;
678 }
679
Andreas Gampe29d38e72016-03-23 15:31:51 +0000680 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
681 Copy(GetDexSrc1(), dex_location);
682 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
683
Calin Juravle357c66d2017-05-04 01:57:17 +0000684 ScopedNonWritable scoped_non_writable(dex_location);
685 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
686
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000687 OatFileAssistant oat_file_assistant(dex_location.c_str(),
688 kRuntimeISA,
689 default_context_.get(),
690 false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000691
692 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000693 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000694 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000695 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000696 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000697 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000698 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000699 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000700
701 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000702 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000703 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100704 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000705}
706
Richard Uhler66d874d2015-01-15 09:37:19 -0800707// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700708// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800709TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000710 if (IsExecutedAsRoot()) {
711 // We cannot simulate non writable locations when executed as root: b/38000545.
712 LOG(ERROR) << "Test skipped because it's running as root";
713 return;
714 }
715
Richard Uhler66d874d2015-01-15 09:37:19 -0800716 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
717 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000718 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800719
Calin Juravle357c66d2017-05-04 01:57:17 +0000720 ScopedNonWritable scoped_non_writable(dex_location);
721 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
722
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000723 OatFileAssistant oat_file_assistant(dex_location.c_str(),
724 kRuntimeISA,
725 default_context_.get(),
726 true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000727 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000728 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100729 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700730
731 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700732 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800733 ASSERT_TRUE(oat_file.get() != nullptr);
734 EXPECT_TRUE(oat_file->IsExecutable());
735 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700736 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
737 EXPECT_EQ(2u, dex_files.size());
738}
739
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000740// Case: We have a MultiDEX file where the non-main multdex entry is out of date.
Richard Uhler67ff7d12015-05-14 13:21:13 -0700741// Expect: The status is kDex2OatNeeded.
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000742TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000743 if (IsExecutedAsRoot()) {
744 // We cannot simulate non writable locations when executed as root: b/38000545.
745 LOG(ERROR) << "Test skipped because it's running as root";
746 return;
747 }
748
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000749 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
Richard Uhler67ff7d12015-05-14 13:21:13 -0700750
751 // Compile code for GetMultiDexSrc1.
752 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000753 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700754
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000755 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
Richard Uhler67ff7d12015-05-14 13:21:13 -0700756 // is out of date.
757 Copy(GetMultiDexSrc2(), dex_location);
758
Calin Juravle357c66d2017-05-04 01:57:17 +0000759 ScopedNonWritable scoped_non_writable(dex_location);
760 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
761
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000762 OatFileAssistant oat_file_assistant(dex_location.c_str(),
763 kRuntimeISA,
764 default_context_.get(),
765 true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000766 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000767 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100768 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000769}
770
Richard Uhler03bc6592016-11-22 09:42:04 +0000771// Case: We have a DEX file and an OAT file out of date with respect to the
772// dex checksum.
773TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000774 if (IsExecutedAsRoot()) {
775 // We cannot simulate non writable locations when executed as root: b/38000545.
776 LOG(ERROR) << "Test skipped because it's running as root";
777 return;
778 }
779
Richard Uhler03bc6592016-11-22 09:42:04 +0000780 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800781
782 // We create a dex, generate an oat for it, then overwrite the dex with a
783 // different dex to make the oat out of date.
784 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000785 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800786 Copy(GetDexSrc2(), dex_location);
787
Calin Juravle357c66d2017-05-04 01:57:17 +0000788 ScopedNonWritable scoped_non_writable(dex_location);
789 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
790
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000791 OatFileAssistant oat_file_assistant(dex_location.c_str(),
792 kRuntimeISA,
793 default_context_.get(),
794 false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000795 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000796 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000797 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000798 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800799
800 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000801 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
802 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100803 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Calin Juravle98071152021-01-27 18:41:58 -0800804
805 VerifyOptimizationStatus(
806 &oat_file_assistant,
807 dex_location,
808 "run-from-apk-fallback",
809 "unknown",
810 "apk-more-recent");
Richard Uhler03bc6592016-11-22 09:42:04 +0000811}
812
Richard Uhler2f27abd2017-01-31 14:02:34 +0000813// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
814// to the dex checksum, but no ODEX file.
815TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000816 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000817 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000818
819 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000820 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
821 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000822 Copy(GetDexSrc2(), dex_location);
823
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000824 OatFileAssistant oat_file_assistant(dex_location.c_str(),
825 kRuntimeISA,
826 default_context_.get(),
827 false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000828
829 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000830 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000831}
832
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000833// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
834// is out of date and there is no corresponding ODEX file.
835TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000836 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000837 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000838
839 Copy(GetMultiDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000840 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
841 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000842 Copy(GetMultiDexSrc2(), dex_location);
843
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000844 OatFileAssistant oat_file_assistant(dex_location.c_str(),
845 kRuntimeISA,
846 default_context_.get(),
847 false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000848
849 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000850 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000851}
852
Richard Uhler03bc6592016-11-22 09:42:04 +0000853// Case: We have a DEX file and an OAT file out of date with respect to the
854// boot image.
855TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000856 if (IsExecutedAsRoot()) {
857 // We cannot simulate non writable locations when executed as root: b/38000545.
858 LOG(ERROR) << "Test skipped because it's running as root";
859 return;
860 }
861
Richard Uhler03bc6592016-11-22 09:42:04 +0000862 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
863
864 Copy(GetDexSrc1(), dex_location);
865 GenerateOatForTest(dex_location.c_str(),
866 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700867 /* with_alternate_image= */ true);
Richard Uhler03bc6592016-11-22 09:42:04 +0000868
Calin Juravle357c66d2017-05-04 01:57:17 +0000869 ScopedNonWritable scoped_non_writable(dex_location);
870 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
871
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000872 OatFileAssistant oat_file_assistant(dex_location.c_str(),
873 kRuntimeISA,
874 default_context_.get(),
875 false);
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000876 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000877 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000878 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000879 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000880 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000881 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +0000882
883 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
884 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
885 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100886 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Calin Juravle98071152021-01-27 18:41:58 -0800887
888 VerifyOptimizationStatus(
889 &oat_file_assistant,
890 dex_location,
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000891 "verify",
Calin Juravle98071152021-01-27 18:41:58 -0800892 "unknown",
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000893 "up-to-date");
Richard Uhler03bc6592016-11-22 09:42:04 +0000894}
895
896// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
897// respect to the boot image.
898// It shouldn't matter that the OAT file is out of date, because it is
899// verify-at-runtime.
900TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000901 if (IsExecutedAsRoot()) {
902 // We cannot simulate non writable locations when executed as root: b/38000545.
903 LOG(ERROR) << "Test skipped because it's running as root";
904 return;
905 }
906
Richard Uhler03bc6592016-11-22 09:42:04 +0000907 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
908
909 Copy(GetDexSrc1(), dex_location);
910 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100911 CompilerFilter::kExtract,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700912 /* with_alternate_image= */ true);
Richard Uhler03bc6592016-11-22 09:42:04 +0000913
Calin Juravle357c66d2017-05-04 01:57:17 +0000914 ScopedNonWritable scoped_non_writable(dex_location);
915 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
916
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000917 OatFileAssistant oat_file_assistant(dex_location.c_str(),
918 kRuntimeISA,
919 default_context_.get(),
920 false);
Richard Uhler03bc6592016-11-22 09:42:04 +0000921 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000922 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000923 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000924 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Richard Uhler03bc6592016-11-22 09:42:04 +0000925
926 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
927 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
928 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100929 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800930}
931
932// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800933TEST_F(OatFileAssistantTest, DexOdexNoOat) {
934 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700935 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800936
937 // Create the dex and odex files
938 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000939 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800940
941 // Verify the status.
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000942 OatFileAssistant oat_file_assistant(dex_location.c_str(),
943 kRuntimeISA,
944 default_context_.get(),
945 false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800946
Andreas Gampe29d38e72016-03-23 15:31:51 +0000947 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000948 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Vladimir Markoe0669322018-09-03 15:44:54 +0100949 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000950 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800951
952 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Vladimir Markoe0669322018-09-03 15:44:54 +0100953 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000954 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100955 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700956
957 // We should still be able to get the non-executable odex file to run from.
958 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
959 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800960}
961
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100962// Case: We have a resource-only DEX file, no ODEX file and no
Richard Uhler9b994ea2015-06-24 08:44:19 -0700963// OAT file. Expect: The status is kNoDexOptNeeded.
964TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
965 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
966
Calin Juravle5ff23932020-12-11 18:26:14 -0800967 Copy(GetResourceOnlySrc1(), dex_location);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700968
969 // Verify the status.
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000970 OatFileAssistant oat_file_assistant(dex_location.c_str(),
971 kRuntimeISA,
972 default_context_.get(),
973 true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700974
Andreas Gampe29d38e72016-03-23 15:31:51 +0000975 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000976 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000977 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000978 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000979 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +0000980 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kVerify));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700981
982 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000983 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
984 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100985 EXPECT_FALSE(oat_file_assistant.HasDexFiles());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700986
Andreas Gampe29d38e72016-03-23 15:31:51 +0000987 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000988 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700989
990 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000991 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
992 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +0100993 EXPECT_FALSE(oat_file_assistant.HasDexFiles());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700994}
995
Vladimir Markoe0669322018-09-03 15:44:54 +0100996// Case: We have a DEX file, an ODEX file and an OAT file.
997// Expect: It shouldn't crash. We should load the odex file executable.
Richard Uhler66d874d2015-01-15 09:37:19 -0800998TEST_F(OatFileAssistantTest, OdexOatOverlap) {
999 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001000 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001001
Calin Juravle357c66d2017-05-04 01:57:17 +00001002 // Create the dex, the odex and the oat files.
Richard Uhler66d874d2015-01-15 09:37:19 -08001003 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001004 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Vladimir Markoe0669322018-09-03 15:44:54 +01001005 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001006
1007 // Verify things don't go bad.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001008 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1009 kRuntimeISA,
1010 default_context_.get(),
1011 true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001012
Vladimir Markoe0669322018-09-03 15:44:54 +01001013 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +00001014 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001015
1016 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Vladimir Markoe0669322018-09-03 15:44:54 +01001017 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
1018 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +01001019 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001020
Richard Uhler66d874d2015-01-15 09:37:19 -08001021 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1022 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -07001023
Vladimir Markoe0669322018-09-03 15:44:54 +01001024 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -08001025 std::vector<std::unique_ptr<const DexFile>> dex_files;
1026 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1027 EXPECT_EQ(1u, dex_files.size());
1028}
1029
Andreas Gampe29d38e72016-03-23 15:31:51 +00001030// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
1031// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
1032TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
1033 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
1034 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +00001035
1036 // Create the dex and odex files
1037 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001038 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
David Brazdilce4b0ba2016-01-28 15:05:49 +00001039
1040 // Verify the status.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001041 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1042 kRuntimeISA,
1043 default_context_.get(),
1044 false);
David Brazdilce4b0ba2016-01-28 15:05:49 +00001045
Andreas Gampe29d38e72016-03-23 15:31:51 +00001046 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +00001047 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +00001048 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Calin Juravle0a5cad32020-02-14 20:29:26 +00001049 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +00001050
1051 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +00001052 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +00001053 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +01001054 EXPECT_TRUE(oat_file_assistant.HasDexFiles());
David Brazdilce4b0ba2016-01-28 15:05:49 +00001055}
1056
Richard Uhler66d874d2015-01-15 09:37:19 -08001057// Case: We have a DEX file and up-to-date OAT file for it.
1058// Expect: We should load an executable dex file.
1059TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001060 if (IsExecutedAsRoot()) {
1061 // We cannot simulate non writable locations when executed as root: b/38000545.
1062 LOG(ERROR) << "Test skipped because it's running as root";
1063 return;
1064 }
1065
Richard Uhler66d874d2015-01-15 09:37:19 -08001066 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
1067
1068 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001069 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001070
Calin Juravle357c66d2017-05-04 01:57:17 +00001071 ScopedNonWritable scoped_non_writable(dex_location);
1072 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1073
Richard Uhler66d874d2015-01-15 09:37:19 -08001074 // Load the oat using an oat file assistant.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001075 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1076 kRuntimeISA,
1077 default_context_.get(),
1078 true);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001079
1080 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1081 ASSERT_TRUE(oat_file.get() != nullptr);
1082 EXPECT_TRUE(oat_file->IsExecutable());
1083 std::vector<std::unique_ptr<const DexFile>> dex_files;
1084 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1085 EXPECT_EQ(1u, dex_files.size());
1086}
1087
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001088// Case: We have a DEX file and up-to-date quicken OAT file for it.
Andreas Gampe29d38e72016-03-23 15:31:51 +00001089// Expect: We should still load the oat file as executable.
1090TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001091 if (IsExecutedAsRoot()) {
1092 // We cannot simulate non writable locations when executed as root: b/38000545.
1093 LOG(ERROR) << "Test skipped because it's running as root";
1094 return;
1095 }
1096
Andreas Gampe29d38e72016-03-23 15:31:51 +00001097 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
1098
1099 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffrayf50975a2020-10-15 13:34:55 +00001100 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kVerify);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001101
Calin Juravle357c66d2017-05-04 01:57:17 +00001102 ScopedNonWritable scoped_non_writable(dex_location);
1103 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1104
Andreas Gampe29d38e72016-03-23 15:31:51 +00001105 // Load the oat using an oat file assistant.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001106 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1107 kRuntimeISA,
1108 default_context_.get(),
1109 true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001110
1111 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1112 ASSERT_TRUE(oat_file.get() != nullptr);
1113 EXPECT_TRUE(oat_file->IsExecutable());
1114 std::vector<std::unique_ptr<const DexFile>> dex_files;
1115 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1116 EXPECT_EQ(1u, dex_files.size());
1117}
1118
1119// Case: We have a DEX file and up-to-date OAT file for it.
1120// Expect: Loading non-executable should load the oat non-executable.
1121TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001122 if (IsExecutedAsRoot()) {
1123 // We cannot simulate non writable locations when executed as root: b/38000545.
1124 LOG(ERROR) << "Test skipped because it's running as root";
1125 return;
1126 }
1127
Richard Uhler66d874d2015-01-15 09:37:19 -08001128 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
1129
1130 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +00001131
1132 ScopedNonWritable scoped_non_writable(dex_location);
1133 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1134
Andreas Gampe29d38e72016-03-23 15:31:51 +00001135 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001136
1137 // Load the oat using an oat file assistant.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001138 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1139 kRuntimeISA,
1140 default_context_.get(),
1141 false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001142
1143 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1144 ASSERT_TRUE(oat_file.get() != nullptr);
1145 EXPECT_FALSE(oat_file->IsExecutable());
1146 std::vector<std::unique_ptr<const DexFile>> dex_files;
1147 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1148 EXPECT_EQ(1u, dex_files.size());
1149}
1150
Richard Uhler66d874d2015-01-15 09:37:19 -08001151// Turn an absolute path into a path relative to the current working
1152// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -08001153static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001154 char buf[MAXPATHLEN];
1155 std::string cwd = getcwd(buf, MAXPATHLEN);
1156
1157 // Split the target and cwd paths into components.
1158 std::vector<std::string> target_path;
1159 std::vector<std::string> cwd_path;
1160 Split(target, '/', &target_path);
1161 Split(cwd, '/', &cwd_path);
1162
1163 // Reverse the path components, so we can use pop_back().
1164 std::reverse(target_path.begin(), target_path.end());
1165 std::reverse(cwd_path.begin(), cwd_path.end());
1166
1167 // Drop the common prefix of the paths. Because we reversed the path
1168 // components, this becomes the common suffix of target_path and cwd_path.
1169 while (!target_path.empty() && !cwd_path.empty()
1170 && target_path.back() == cwd_path.back()) {
1171 target_path.pop_back();
1172 cwd_path.pop_back();
1173 }
1174
1175 // For each element of the remaining cwd_path, add '..' to the beginning
1176 // of the target path. Because we reversed the path components, we add to
1177 // the end of target_path.
1178 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1179 target_path.push_back("..");
1180 }
1181
1182 // Reverse again to get the right path order, and join to get the result.
1183 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001184 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001185}
1186
1187// Case: Non-absolute path to Dex location.
1188// Expect: Not sure, but it shouldn't crash.
1189TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1190 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1191 Copy(GetDexSrc1(), abs_dex_location);
1192
1193 std::string dex_location = MakePathRelative(abs_dex_location);
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001194 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1195 kRuntimeISA,
1196 default_context_.get(),
1197 true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001198
1199 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001200 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +00001201 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001202 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1203 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001204}
1205
1206// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001207// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001208TEST_F(OatFileAssistantTest, ShortDexLocation) {
1209 std::string dex_location = "/xx";
1210
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001211 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1212 kRuntimeISA,
1213 default_context_.get(),
1214 true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001215
1216 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001217 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Calin Juravle0a5cad32020-02-14 20:29:26 +00001218 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001219 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1220 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +01001221 EXPECT_FALSE(oat_file_assistant.HasDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001222}
1223
1224// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001225// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001226TEST_F(OatFileAssistantTest, LongDexExtension) {
1227 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1228 Copy(GetDexSrc1(), dex_location);
1229
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001230 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1231 kRuntimeISA,
1232 default_context_.get(),
1233 false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001234
Richard Uhler7225a8d2016-11-22 10:12:03 +00001235 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Calin Juravle0a5cad32020-02-14 20:29:26 +00001236 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001237
1238 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001239 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1240 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001241}
1242
1243// A task to generate a dex location. Used by the RaceToGenerate test.
1244class RaceGenerateTask : public Task {
1245 public:
Vladimir Markob9c29f62019-03-20 14:22:51 +00001246 RaceGenerateTask(OatFileAssistantTest& test,
1247 const std::string& dex_location,
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001248 const std::string& oat_location,
1249 Mutex* lock)
Vladimir Markob9c29f62019-03-20 14:22:51 +00001250 : test_(test),
1251 dex_location_(dex_location),
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001252 oat_location_(oat_location),
1253 lock_(lock),
1254 loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001255 {}
1256
Andreas Gampefa6a1b02018-09-07 08:11:55 -07001257 void Run(Thread* self ATTRIBUTE_UNUSED) override {
Richard Uhler66d874d2015-01-15 09:37:19 -08001258 // Load the dex files, and save a pointer to the loaded oat file, so that
1259 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001260 std::vector<std::unique_ptr<const DexFile>> dex_files;
1261 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001262 const OatFile* oat_file = nullptr;
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001263 {
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001264 MutexLock mu(Thread::Current(), *lock_);
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001265 // Create the oat file.
1266 std::vector<std::string> args;
1267 args.push_back("--dex-file=" + dex_location_);
1268 args.push_back("--oat-file=" + oat_location_);
1269 std::string error_msg;
Vladimir Markob9c29f62019-03-20 14:22:51 +00001270 ASSERT_TRUE(test_.Dex2Oat(args, &error_msg)) << error_msg;
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001271 }
1272
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001273 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1274 dex_location_.c_str(),
Jeff Hao0cb17282017-07-12 14:51:49 -07001275 Runtime::Current()->GetSystemClassLoader(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001276 /*dex_elements=*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001277 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001278 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001279 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001280 if (dex_files[0]->GetOatDexFile() != nullptr) {
1281 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
1282 }
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001283 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001284 }
1285
1286 const OatFile* GetLoadedOatFile() const {
1287 return loaded_oat_file_;
1288 }
1289
1290 private:
Vladimir Markob9c29f62019-03-20 14:22:51 +00001291 OatFileAssistantTest& test_;
Richard Uhler66d874d2015-01-15 09:37:19 -08001292 std::string dex_location_;
1293 std::string oat_location_;
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001294 Mutex* lock_;
Richard Uhler66d874d2015-01-15 09:37:19 -08001295 const OatFile* loaded_oat_file_;
1296};
1297
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001298// Test the case where dex2oat invocations race with multiple processes trying to
1299// load the oat file.
Richard Uhler66d874d2015-01-15 09:37:19 -08001300TEST_F(OatFileAssistantTest, RaceToGenerate) {
1301 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001302 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001303
Jeff Hao0cb17282017-07-12 14:51:49 -07001304 // Start the runtime to initialize the system's class loader.
1305 Thread::Current()->TransitionFromSuspendedToRunnable();
1306 runtime_->Start();
1307
Richard Uhler66d874d2015-01-15 09:37:19 -08001308 // We use the lib core dex file, because it's large, and hopefully should
1309 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001310 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001311
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001312 const size_t kNumThreads = 32;
Richard Uhler66d874d2015-01-15 09:37:19 -08001313 Thread* self = Thread::Current();
1314 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1315 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001316 Mutex lock("RaceToGenerate");
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001317 for (size_t i = 0; i < kNumThreads; i++) {
Vladimir Markob9c29f62019-03-20 14:22:51 +00001318 std::unique_ptr<RaceGenerateTask> task(
1319 new RaceGenerateTask(*this, dex_location, oat_location, &lock));
Richard Uhler66d874d2015-01-15 09:37:19 -08001320 thread_pool.AddTask(self, task.get());
1321 tasks.push_back(std::move(task));
1322 }
1323 thread_pool.StartWorkers(self);
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001324 thread_pool.Wait(self, /* do_work= */ true, /* may_hold_locks= */ false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001325
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001326 // Verify that tasks which got an oat file got a unique one.
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001327 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001328 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001329 const OatFile* oat_file = task->GetLoadedOatFile();
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001330 if (oat_file != nullptr) {
1331 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1332 oat_files.insert(oat_file);
1333 }
Richard Uhler66d874d2015-01-15 09:37:19 -08001334 }
1335}
1336
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001337// Case: We have a DEX file and an ODEX file, and no OAT file,
Vladimir Markoe0669322018-09-03 15:44:54 +01001338// Expect: We should load the odex file executable.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001339TEST_F(OatFileAssistantTest, LoadDexOdexNoOat) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001340 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001341 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001342
1343 // Create the dex and odex files
1344 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001345 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001346
1347 // Load the oat using an executable oat file assistant.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001348 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1349 kRuntimeISA,
1350 default_context_.get(),
1351 true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001352
1353 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1354 ASSERT_TRUE(oat_file.get() != nullptr);
Vladimir Markoe0669322018-09-03 15:44:54 +01001355 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -08001356 std::vector<std::unique_ptr<const DexFile>> dex_files;
1357 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1358 EXPECT_EQ(1u, dex_files.size());
1359}
1360
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001361// Case: We have a MultiDEX file and an ODEX file, and no OAT file.
Vladimir Markoe0669322018-09-03 15:44:54 +01001362// Expect: We should load the odex file executable.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001363TEST_F(OatFileAssistantTest, LoadMultiDexOdexNoOat) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001364 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001365 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001366
1367 // Create the dex and odex files
1368 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001369 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001370
1371 // Load the oat using an executable oat file assistant.
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001372 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1373 kRuntimeISA,
1374 default_context_.get(),
1375 true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001376
1377 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1378 ASSERT_TRUE(oat_file.get() != nullptr);
Vladimir Markoe0669322018-09-03 15:44:54 +01001379 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -08001380 std::vector<std::unique_ptr<const DexFile>> dex_files;
1381 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1382 EXPECT_EQ(2u, dex_files.size());
1383}
1384
Richard Uhlerb81881d2016-04-19 13:08:04 -07001385TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001386 std::string error_msg;
1387 std::string odex_file;
1388
Richard Uhlerb81881d2016-04-19 13:08:04 -07001389 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001390 "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001391 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001392
Richard Uhlerb81881d2016-04-19 13:08:04 -07001393 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001394 "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001395 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001396
Richard Uhlerb81881d2016-04-19 13:08:04 -07001397 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001398 "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001399 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001400 "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001401}
1402
Richard Uhler23cedd22015-04-08 13:17:29 -07001403// Verify the dexopt status values from dalvik.system.DexFile
1404// match the OatFileAssistant::DexOptStatus values.
1405TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001406 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1407 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1408 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1409 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1410 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001411 };
1412
Richard Uhler23cedd22015-04-08 13:17:29 -07001413 ScopedObjectAccess soa(Thread::Current());
1414 StackHandleScope<1> hs(soa.Self());
1415 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1416 Handle<mirror::Class> dexfile(
1417 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
Andreas Gampefa4333d2017-02-14 11:10:34 -08001418 ASSERT_FALSE(dexfile == nullptr);
Richard Uhler23cedd22015-04-08 13:17:29 -07001419 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1420
Richard Uhler7225a8d2016-11-22 10:12:03 +00001421 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1422 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001423 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001424 ASSERT_FALSE(art_field == nullptr);
1425 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1426 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1427 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001428}
Richard Uhler66d874d2015-01-15 09:37:19 -08001429
Calin Juravle44e5efa2017-09-12 00:54:26 -07001430TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
1431 std::string dex_location = GetScratchDir() + "/TestDex.jar";
Calin Juravleaf322422020-02-11 13:45:53 -08001432 std::string odex_location = GetOdexDir() + "/TestDex.odex";
1433
Calin Juravle44e5efa2017-09-12 00:54:26 -07001434 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1435 Copy(GetDexSrc1(), dex_location);
1436 Copy(GetDexSrc2(), context_location);
1437
Calin Juravle44e5efa2017-09-12 00:54:26 -07001438 std::string context_str = "PCL[" + context_location + "]";
Calin Juravleaf322422020-02-11 13:45:53 -08001439
Calin Juravle44e5efa2017-09-12 00:54:26 -07001440 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1441 ASSERT_TRUE(context != nullptr);
Calin Juravle5ff23932020-12-11 18:26:14 -08001442 ASSERT_TRUE(context->OpenDexFiles());
Calin Juravle44e5efa2017-09-12 00:54:26 -07001443
Calin Juravleaf322422020-02-11 13:45:53 -08001444 std::string error_msg;
1445 std::vector<std::string> args;
1446 args.push_back("--dex-file=" + dex_location);
1447 args.push_back("--oat-file=" + odex_location);
1448 args.push_back("--class-loader-context=" + context_str);
1449 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
1450
Calin Juravle44e5efa2017-09-12 00:54:26 -07001451 // Update the context by overriding the jar file.
1452 Copy(GetMultiDexSrc2(), context_location);
Calin Juravleaf322422020-02-11 13:45:53 -08001453
1454 {
Calin Juravle0a5cad32020-02-14 20:29:26 +00001455 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1456 ASSERT_TRUE(updated_context != nullptr);
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001457 std::vector<int> context_fds;
1458 ASSERT_TRUE(updated_context->OpenDexFiles("", context_fds, /*only_read_checksums*/ true));
1459 OatFileAssistant oat_file_assistant(
1460 dex_location.c_str(), kRuntimeISA, updated_context.get(), false);
1461 // DexOptNeeded should advise compilation for filter when the context changes.
1462 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
1463 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kDefaultCompilerFilter));
Calin Juravleaf322422020-02-11 13:45:53 -08001464 }
1465 {
Calin Juravle0a5cad32020-02-14 20:29:26 +00001466 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1467 ASSERT_TRUE(updated_context != nullptr);
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001468 std::vector<int> context_fds;
1469 ASSERT_TRUE(updated_context->OpenDexFiles("", context_fds, /*only_read_checksums*/ true));
1470 OatFileAssistant oat_file_assistant(
1471 dex_location.c_str(), kRuntimeISA, updated_context.get(), false);
Calin Juravleaf322422020-02-11 13:45:53 -08001472 // Now check that DexOptNeeded does not advise compilation if we only extracted the file.
1473 args.push_back("--compiler-filter=extract");
1474 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
1475 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray525fa422021-04-19 07:50:35 +00001476 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
1477 }
1478 {
1479 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1480 ASSERT_TRUE(updated_context != nullptr);
1481 std::vector<int> context_fds;
1482 ASSERT_TRUE(updated_context->OpenDexFiles("", context_fds, /*only_read_checksums*/ true));
1483 OatFileAssistant oat_file_assistant(
1484 dex_location.c_str(), kRuntimeISA, updated_context.get(), false);
1485 // Now check that DexOptNeeded does not advise compilation if we only verify the file.
1486 args.push_back("--compiler-filter=verify");
1487 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
1488 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1489 GetDexOptNeeded(&oat_file_assistant, CompilerFilter::kExtract));
Calin Juravleaf322422020-02-11 13:45:53 -08001490 }
Nicolas Geoffray29742602017-12-14 10:09:03 +00001491}
1492
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001493// Test that GetLocation of a dex file is the same whether the dex
1494// filed is backed by an oat file or not.
1495TEST_F(OatFileAssistantTest, GetDexLocation) {
1496 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1497 std::string oat_location = GetOdexDir() + "/TestDex.odex";
Eric Holkbc89ed42020-04-29 19:59:24 +00001498 std::string art_location = GetOdexDir() + "/TestDex.art";
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001499
1500 // Start the runtime to initialize the system's class loader.
1501 Thread::Current()->TransitionFromSuspendedToRunnable();
1502 runtime_->Start();
1503
1504 Copy(GetDexSrc1(), dex_location);
1505
1506 std::vector<std::unique_ptr<const DexFile>> dex_files;
1507 std::vector<std::string> error_msgs;
1508 const OatFile* oat_file = nullptr;
1509
1510 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1511 dex_location.c_str(),
1512 Runtime::Current()->GetSystemClassLoader(),
1513 /*dex_elements=*/nullptr,
1514 &oat_file,
1515 &error_msgs);
Vladimir Markob7bf8432019-12-03 13:18:50 +00001516 ASSERT_EQ(dex_files.size(), 1u) << android::base::Join(error_msgs, "\n");
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001517 EXPECT_EQ(oat_file, nullptr);
1518 std::string stored_dex_location = dex_files[0]->GetLocation();
1519 {
1520 // Create the oat file.
1521 std::vector<std::string> args;
1522 args.push_back("--dex-file=" + dex_location);
1523 args.push_back("--dex-location=TestDex.jar");
1524 args.push_back("--oat-file=" + oat_location);
Eric Holkbc89ed42020-04-29 19:59:24 +00001525 args.push_back("--app-image-file=" + art_location);
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001526 std::string error_msg;
1527 ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
1528 }
1529 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1530 dex_location.c_str(),
1531 Runtime::Current()->GetSystemClassLoader(),
1532 /*dex_elements=*/nullptr,
1533 &oat_file,
1534 &error_msgs);
Vladimir Markob7bf8432019-12-03 13:18:50 +00001535 ASSERT_EQ(dex_files.size(), 1u) << android::base::Join(error_msgs, "\n");
1536 ASSERT_NE(oat_file, nullptr);
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001537 std::string oat_stored_dex_location = dex_files[0]->GetLocation();
1538 EXPECT_EQ(oat_stored_dex_location, stored_dex_location);
1539}
1540
1541// Test that a dex file on the platform location gets the right hiddenapi domain,
1542// regardless of whether it has a backing oat file.
1543TEST_F(OatFileAssistantTest, SystemFrameworkDir) {
1544 std::string filebase = "OatFileAssistantTestSystemFrameworkDir";
1545 std::string dex_location = GetAndroidRoot() + "/framework/" + filebase + ".jar";
1546 Copy(GetDexSrc1(), dex_location);
1547
1548 std::string odex_dir = GetAndroidRoot() + "/framework/oat/";
1549 mkdir(odex_dir.c_str(), 0700);
1550 odex_dir = odex_dir + std::string(GetInstructionSetString(kRuntimeISA));
1551 mkdir(odex_dir.c_str(), 0700);
1552 std::string oat_location = odex_dir + "/" + filebase + ".odex";
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001553 std::string vdex_location = odex_dir + "/" + filebase + ".vdex";
Eric Holkbc89ed42020-04-29 19:59:24 +00001554 std::string art_location = odex_dir + "/" + filebase + ".art";
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001555 // Clean up in case previous run crashed.
1556 remove(oat_location.c_str());
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +00001557 remove(vdex_location.c_str());
1558 remove(art_location.c_str());
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001559
1560 // Start the runtime to initialize the system's class loader.
1561 Thread::Current()->TransitionFromSuspendedToRunnable();
1562 runtime_->Start();
1563
1564 std::vector<std::unique_ptr<const DexFile>> dex_files_first;
1565 std::vector<std::unique_ptr<const DexFile>> dex_files_second;
1566 std::vector<std::string> error_msgs;
1567 const OatFile* oat_file = nullptr;
1568
1569 dex_files_first = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1570 dex_location.c_str(),
1571 Runtime::Current()->GetSystemClassLoader(),
1572 /*dex_elements=*/nullptr,
1573 &oat_file,
1574 &error_msgs);
Vladimir Markob7bf8432019-12-03 13:18:50 +00001575 ASSERT_EQ(dex_files_first.size(), 1u) << android::base::Join(error_msgs, "\n");
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001576 EXPECT_EQ(oat_file, nullptr) << dex_location;
1577 EXPECT_EQ(dex_files_first[0]->GetOatDexFile(), nullptr);
1578
1579 // Register the dex file to get a domain.
1580 {
1581 ScopedObjectAccess soa(Thread::Current());
1582 Runtime::Current()->GetClassLinker()->RegisterDexFile(
1583 *dex_files_first[0],
1584 soa.Decode<mirror::ClassLoader>(Runtime::Current()->GetSystemClassLoader()));
1585 }
1586 std::string stored_dex_location = dex_files_first[0]->GetLocation();
1587 EXPECT_EQ(dex_files_first[0]->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
1588 {
1589 // Create the oat file.
1590 std::vector<std::string> args;
1591 args.push_back("--dex-file=" + dex_location);
1592 args.push_back("--dex-location=" + filebase + ".jar");
1593 args.push_back("--oat-file=" + oat_location);
Eric Holkbc89ed42020-04-29 19:59:24 +00001594 args.push_back("--app-image-file=" + art_location);
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001595 std::string error_msg;
1596 ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
1597 }
1598 dex_files_second = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1599 dex_location.c_str(),
1600 Runtime::Current()->GetSystemClassLoader(),
1601 /*dex_elements=*/nullptr,
1602 &oat_file,
1603 &error_msgs);
Vladimir Markob7bf8432019-12-03 13:18:50 +00001604 ASSERT_EQ(dex_files_second.size(), 1u) << android::base::Join(error_msgs, "\n");
1605 ASSERT_NE(oat_file, nullptr);
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001606 EXPECT_NE(dex_files_second[0]->GetOatDexFile(), nullptr);
1607 EXPECT_NE(dex_files_second[0]->GetOatDexFile()->GetOatFile(), nullptr);
1608
1609 // Register the dex file to get a domain.
1610 {
1611 ScopedObjectAccess soa(Thread::Current());
1612 Runtime::Current()->GetClassLinker()->RegisterDexFile(
1613 *dex_files_second[0],
1614 soa.Decode<mirror::ClassLoader>(Runtime::Current()->GetSystemClassLoader()));
1615 }
1616 std::string oat_stored_dex_location = dex_files_second[0]->GetLocation();
1617 EXPECT_EQ(oat_stored_dex_location, stored_dex_location);
1618 EXPECT_EQ(dex_files_second[0]->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
1619 EXPECT_EQ(0, remove(oat_location.c_str()));
1620}
1621
Eric Holkbc89ed42020-04-29 19:59:24 +00001622// Make sure OAT files that require app images are not loaded as executable.
1623TEST_F(OatFileAssistantTest, LoadOatNoArt) {
1624 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1625 std::string odex_location = GetOdexDir() + "/TestDex.odex";
1626 std::string art_location = GetOdexDir() + "/TestDex.art";
1627 Copy(GetDexSrc1(), dex_location);
1628 GenerateOdexForTest(dex_location,
1629 odex_location,
1630 CompilerFilter::kSpeed,
1631 "install",
1632 {
1633 "--app-image-file=" + art_location,
1634 });
1635
1636 unlink(art_location.c_str());
1637
1638 std::vector<std::string> error_msgs;
1639 const OatFile* oat_file = nullptr;
1640
1641 // Start the runtime to initialize the system's class loader.
1642 Thread::Current()->TransitionFromSuspendedToRunnable();
1643 runtime_->Start();
1644
1645 const auto dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1646 dex_location.c_str(),
1647 Runtime::Current()->GetSystemClassLoader(),
1648 /*dex_elements=*/nullptr,
1649 &oat_file,
1650 &error_msgs);
1651
1652 EXPECT_FALSE(dex_files.empty());
Nicolas Geoffray90a18cf2020-06-25 15:12:59 +01001653 ASSERT_NE(oat_file, nullptr);
Eric Holkbc89ed42020-04-29 19:59:24 +00001654 EXPECT_FALSE(oat_file->IsExecutable());
1655}
1656
Nicolas Geoffrayd3c45c22021-04-27 13:21:28 +01001657TEST_F(OatFileAssistantTest, GetDexOptNeededWithApexVersions) {
1658 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1659 std::string odex_location = GetOdexDir() + "/TestDex.odex";
1660 Copy(GetDexSrc1(), dex_location);
1661
1662 // Test that using the current's runtime apex versions works.
1663 {
1664 std::string error_msg;
1665 std::vector<std::string> args;
1666 args.push_back("--dex-file=" + dex_location);
1667 args.push_back("--oat-file=" + odex_location);
1668 args.push_back("--apex-versions=" + Runtime::Current()->GetApexVersions());
1669 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
1670
1671 OatFileAssistant oat_file_assistant(
1672 dex_location.c_str(), kRuntimeISA, default_context_.get(), false);
1673 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
1674 }
1675
1676 // Test that a subset of apex versions works.
1677 {
1678 std::string error_msg;
1679 std::vector<std::string> args;
1680 args.push_back("--dex-file=" + dex_location);
1681 args.push_back("--oat-file=" + odex_location);
1682 args.push_back("--apex-versions=" + Runtime::Current()->GetApexVersions().substr(0, 1));
1683 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
1684
1685 OatFileAssistant oat_file_assistant(
1686 dex_location.c_str(), kRuntimeISA, default_context_.get(), false);
1687 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
1688 }
1689
1690 // Test that different apex versions require to recompile.
1691 {
1692 std::string error_msg;
1693 std::vector<std::string> args;
1694 args.push_back("--dex-file=" + dex_location);
1695 args.push_back("--oat-file=" + odex_location);
1696 args.push_back("--apex-versions=/1/2/3/4");
1697 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
1698
1699 OatFileAssistant oat_file_assistant(
1700 dex_location.c_str(), kRuntimeISA, default_context_.get(), false);
1701 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, oat_file_assistant.OdexFileStatus());
1702 }
1703}
1704
Richard Uhler66d874d2015-01-15 09:37:19 -08001705// TODO: More Tests:
1706// * Test class linker falls back to unquickened dex for DexNoOat
1707// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001708// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001709// * Test for status of oat while oat is being generated (how?)
1710// * Test case where 32 and 64 bit boot class paths differ,
1711// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1712// 64 bit boot class paths.
1713// * Test unexpected scenarios (?):
1714// - Dex is stripped, don't have odex.
1715// - Oat file corrupted after status check, before reload unexecutable
1716// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001717} // namespace art