blob: 32ae42eef5c496be7fc5e869521f739ab0877208 [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:
47 void VerifyOptimizationStatus(const std::string& file,
48 const std::string& expected_filter,
49 const std::string& expected_reason) {
50 std::string compilation_filter;
51 std::string compilation_reason;
52 OatFileAssistant::GetOptimizationStatus(
53 file, kRuntimeISA, &compilation_filter, &compilation_reason);
54
55 ASSERT_EQ(expected_filter, compilation_filter);
56 ASSERT_EQ(expected_reason, compilation_reason);
57 }
58
59 void VerifyOptimizationStatus(const std::string& file,
60 CompilerFilter::Filter expected_filter,
61 const std::string& expected_reason) {
62 VerifyOptimizationStatus(
63 file, CompilerFilter::NameOfFilter(expected_filter), expected_reason);
64 }
Vladimir Markof3d88a82018-12-21 16:38:47 +000065 void InsertNewBootClasspathEntry() {
66 std::string extra_dex_filename = GetMultiDexSrc1();
67 Runtime* runtime = Runtime::Current();
68 runtime->boot_class_path_.push_back(extra_dex_filename);
69 if (!runtime->boot_class_path_locations_.empty()) {
70 runtime->boot_class_path_locations_.push_back(extra_dex_filename);
71 }
72 }
Calin Juravle5f9a8012018-02-12 20:27:46 -080073};
Richard Uhler66d874d2015-01-15 09:37:19 -080074
Calin Juravle357c66d2017-05-04 01:57:17 +000075class ScopedNonWritable {
76 public:
77 explicit ScopedNonWritable(const std::string& dex_location) {
78 is_valid_ = false;
79 size_t pos = dex_location.rfind('/');
80 if (pos != std::string::npos) {
81 is_valid_ = true;
82 dex_parent_ = dex_location.substr(0, pos);
83 if (chmod(dex_parent_.c_str(), 0555) != 0) {
84 PLOG(ERROR) << "Could not change permissions on " << dex_parent_;
85 }
86 }
87 }
88
89 bool IsSuccessful() { return is_valid_ && (access(dex_parent_.c_str(), W_OK) != 0); }
90
91 ~ScopedNonWritable() {
92 if (is_valid_) {
93 if (chmod(dex_parent_.c_str(), 0777) != 0) {
94 PLOG(ERROR) << "Could not restore permissions on " << dex_parent_;
95 }
96 }
97 }
98
99 private:
100 std::string dex_parent_;
101 bool is_valid_;
102};
103
104static bool IsExecutedAsRoot() {
105 return geteuid() == 0;
106}
Calin Juravle36eb3132017-01-13 16:32:38 -0800107
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000108// Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
109// encoded dex locations.
110// Expect: The oat file status is kNoDexOptNeeded.
111TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
112 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
113 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
114
115 // Create the dex file
116 Copy(GetMultiDexSrc1(), dex_location);
117
118 // Create the oat file with relative encoded dex location.
119 std::vector<std::string> args = {
120 "--dex-file=" + dex_location,
121 "--dex-location=" + std::string("RelativeEncodedDexLocation.jar"),
122 "--oat-file=" + odex_location,
123 "--compiler-filter=speed"
124 };
125
126 std::string error_msg;
127 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
128
129 // Verify we can load both dex files.
130 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
131
132 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
133 ASSERT_TRUE(oat_file.get() != nullptr);
134 EXPECT_TRUE(oat_file->IsExecutable());
135 std::vector<std::unique_ptr<const DexFile>> dex_files;
136 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
137 EXPECT_EQ(2u, dex_files.size());
138}
139
140TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
141 std::string dex_location = GetScratchDir() + "/TestDex.jar";
142 std::string odex_location = GetOdexDir() + "/TestDex.odex";
143 std::string context_location = GetScratchDir() + "/ContextDex.jar";
144 Copy(GetDexSrc1(), dex_location);
145 Copy(GetDexSrc2(), context_location);
146
147 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
148
149 std::string context_str = "PCL[" + context_location + "]";
150 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
151 ASSERT_TRUE(context != nullptr);
152 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
153
154 std::string error_msg;
155 std::vector<std::string> args;
156 args.push_back("--dex-file=" + dex_location);
157 args.push_back("--oat-file=" + odex_location);
158 args.push_back("--class-loader-context=" + context_str);
159 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
160
161 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
162 EXPECT_NE(nullptr, oat_file.get());
163 EXPECT_EQ(context->EncodeContextForOatFile(""),
164 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
165}
166
167TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
168 std::string dex_location = GetScratchDir() + "/TestDex.jar";
169 std::string odex_location = GetOdexDir() + "/TestDex.odex";
170 std::string context_location = GetScratchDir() + "/ContextDex.jar";
171 Copy(GetDexSrc1(), dex_location);
172 Copy(GetDexSrc2(), context_location);
173
174 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
175
176 std::string context_str = "PCL[" + context_location + "]";
177 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
178 ASSERT_TRUE(context != nullptr);
179 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
180
181 std::string error_msg;
182 std::vector<std::string> args;
183 args.push_back("--dex-file=" + dex_location);
184 args.push_back("--oat-file=" + odex_location);
185 args.push_back("--class-loader-context=" + context_str);
186 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
187
188 // A relative context simulates a dependent split context.
189 std::unique_ptr<ClassLoaderContext> relative_context =
190 ClassLoaderContext::Create("PCL[ContextDex.jar]");
191 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
192 oat_file_assistant.GetDexOptNeeded(
193 CompilerFilter::kDefaultCompilerFilter,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700194 /* profile_changed= */ false,
195 /* downgrade= */ false,
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000196 relative_context.get()));
197}
198
Richard Uhler66d874d2015-01-15 09:37:19 -0800199// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700200// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800201TEST_F(OatFileAssistantTest, DexNoOat) {
202 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
203 Copy(GetDexSrc1(), dex_location);
204
Richard Uhlerd1472a22016-04-15 15:18:56 -0700205 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800206
Richard Uhler7225a8d2016-11-22 10:12:03 +0000207 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100208 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000209 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100210 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000211 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000212 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000213 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000214 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800215
216 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000217 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
218 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700219 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800220
221 VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
Richard Uhler66d874d2015-01-15 09:37:19 -0800222}
223
224// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700225// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800226TEST_F(OatFileAssistantTest, NoDexNoOat) {
227 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
228
Richard Uhlerd1472a22016-04-15 15:18:56 -0700229 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800230
Andreas Gampe29d38e72016-03-23 15:31:51 +0000231 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
232 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700233 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
234
Richard Uhler9b994ea2015-06-24 08:44:19 -0700235 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800236 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
237 EXPECT_EQ(nullptr, oat_file.get());
238}
239
Vladimir Markoe0669322018-09-03 15:44:54 +0100240// Case: We have a DEX file and an ODEX file, but no OAT file.
241// Expect: The status is kNoDexOptNeeded.
Calin Juravle357c66d2017-05-04 01:57:17 +0000242TEST_F(OatFileAssistantTest, OdexUpToDate) {
243 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
244 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
245 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100246 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000247
Vladimir Markof3d88a82018-12-21 16:38:47 +0000248 // Force the use of oat location by making the dex parent not writable.
249 OatFileAssistant oat_file_assistant(
250 dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false);
Calin Juravle357c66d2017-05-04 01:57:17 +0000251
252 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Vladimir Markof3d88a82018-12-21 16:38:47 +0000253 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Calin Juravle357c66d2017-05-04 01:57:17 +0000254 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Vladimir Markof3d88a82018-12-21 16:38:47 +0000255 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Calin Juravle357c66d2017-05-04 01:57:17 +0000256 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Vladimir Markof3d88a82018-12-21 16:38:47 +0000257 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Calin Juravle357c66d2017-05-04 01:57:17 +0000258 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Vladimir Markof3d88a82018-12-21 16:38:47 +0000259 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
260
261 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
262 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
263 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
264 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
265
266 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
267}
268
269// Case: We have an ODEX file compiled against partial boot image.
270// Expect: The status is kNoDexOptNeeded.
271TEST_F(OatFileAssistantTest, OdexUpToDatePartialBootImage) {
272 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
273 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
274 Copy(GetDexSrc1(), dex_location);
275 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
276
277 // Insert an extra dex file to the boot class path.
278 InsertNewBootClasspathEntry();
279
280 // Force the use of oat location by making the dex parent not writable.
281 OatFileAssistant oat_file_assistant(
282 dex_location.c_str(), kRuntimeISA, /*load_executable=*/ false);
283
284 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
285 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
286 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
287 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
288 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
289 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
290 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
291 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Calin Juravle357c66d2017-05-04 01:57:17 +0000292
293 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
294 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
295 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
296 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800297
298 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000299}
300
301// Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
302// file via a symlink.
Vladimir Markoe0669322018-09-03 15:44:54 +0100303// Expect: The status is kNoDexOptNeeded.
Calin Juravle357c66d2017-05-04 01:57:17 +0000304TEST_F(OatFileAssistantTest, OdexUpToDateSymLink) {
305 std::string scratch_dir = GetScratchDir();
306 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
307 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
308
309 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100310 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle357c66d2017-05-04 01:57:17 +0000311
312 // Now replace the dex location with a symlink.
313 std::string link = scratch_dir + "/link";
314 ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str()));
315 dex_location = link + "/OdexUpToDate.jar";
316
317 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
318
319 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
320 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
321 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
322 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
323 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
324 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
325 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
326 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
327
328 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
329 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
330 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
331 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
332}
333
Richard Uhler66d874d2015-01-15 09:37:19 -0800334// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700335// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800336TEST_F(OatFileAssistantTest, OatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000337 if (IsExecutedAsRoot()) {
338 // We cannot simulate non writable locations when executed as root: b/38000545.
339 LOG(ERROR) << "Test skipped because it's running as root";
340 return;
341 }
342
Richard Uhler66d874d2015-01-15 09:37:19 -0800343 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
344 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000345 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800346
Vladimir Markof3d88a82018-12-21 16:38:47 +0000347 // Force the use of oat location by making the dex parent not writable.
Calin Juravle357c66d2017-05-04 01:57:17 +0000348 ScopedNonWritable scoped_non_writable(dex_location);
349 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
350
351 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
352
353 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
354 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
355 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
356 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
357 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
358 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
359 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
360 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
361
362 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
363 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
364 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
365 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800366
367 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "unknown");
Calin Juravle357c66d2017-05-04 01:57:17 +0000368}
369
Vladimir Markoe0669322018-09-03 15:44:54 +0100370// Case: Passing valid file descriptors of updated odex/vdex files along with the dex file.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700371// Expect: The status is kNoDexOptNeeded.
372TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) {
373 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
374 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
375 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
376
377 Copy(GetDexSrc1(), dex_location);
378 GenerateOatForTest(dex_location.c_str(),
379 odex_location.c_str(),
380 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700381 /* with_alternate_image= */ false);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700382
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700383 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY | O_CLOEXEC));
384 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY | O_CLOEXEC));
385 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700386
387 OatFileAssistant oat_file_assistant(dex_location.c_str(),
388 kRuntimeISA,
389 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000390 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700391 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700392 odex_fd.get(),
393 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700394 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
395 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
396 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
397 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
398 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
399 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
400 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
401 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
402
403 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
404 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
405 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
406 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
407}
408
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700409// Case: Passing invalid odex fd and valid vdex and zip fds.
410// Expect: The status should be kDex2OatForBootImage.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700411TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
412 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
413 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
414 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
415
416 Copy(GetDexSrc1(), dex_location);
417 GenerateOatForTest(dex_location.c_str(),
418 odex_location.c_str(),
419 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700420 /* with_alternate_image= */ false);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700421
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700422 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY | O_CLOEXEC));
423 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700424
425 OatFileAssistant oat_file_assistant(dex_location.c_str(),
426 kRuntimeISA,
427 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000428 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700429 vdex_fd.get(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700430 /* oat_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700431 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700432 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
433 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700434 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
435 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
436
437 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700438 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
439 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700440 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700441}
442
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700443// Case: Passing invalid vdex fd and valid odex and zip fds.
444// Expect: The status should be kDex2OatFromScratch.
445TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
446 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
447 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
448
449 Copy(GetDexSrc1(), dex_location);
450 GenerateOatForTest(dex_location.c_str(),
451 odex_location.c_str(),
452 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700453 /* with_alternate_image= */ false);
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700454
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700455 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY | O_CLOEXEC));
456 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700457
458 OatFileAssistant oat_file_assistant(dex_location.c_str(),
459 kRuntimeISA,
460 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000461 false,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700462 /* vdex_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700463 odex_fd.get(),
464 zip_fd.get());
465
466 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
467 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
468 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
469 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
470 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
471 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
472}
473
474// Case: Passing invalid vdex and odex fd with valid zip fd.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700475// Expect: The status is kDex2oatFromScratch.
476TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
477 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
478
479 Copy(GetDexSrc1(), dex_location);
480
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700481 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700482 OatFileAssistant oat_file_assistant(dex_location.c_str(),
483 kRuntimeISA,
484 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000485 false,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700486 /* vdex_fd= */ -1,
487 /* oat_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700488 zip_fd);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700489 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
490 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
491 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
492 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
493}
494
Richard Uhler2f27abd2017-01-31 14:02:34 +0000495// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
496// ODEX file.
497TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000498 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000499 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000500
Richard Uhler9a37efc2016-08-05 16:32:55 -0700501 Copy(GetDexSrc1(), dex_location);
502
Richard Uhler2f27abd2017-01-31 14:02:34 +0000503 // Generating and deleting the oat file should have the side effect of
504 // creating an up-to-date vdex file.
Calin Juravle357c66d2017-05-04 01:57:17 +0000505 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
506 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000507
Calin Juravle357c66d2017-05-04 01:57:17 +0000508 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000509
510 // Even though the vdex file is up to date, because we don't have the oat
511 // file, we can't know that the vdex depends on the boot image and is up to
512 // date with respect to the boot image. Instead we must assume the vdex file
513 // depends on the boot image and is out of date with respect to the boot
514 // image.
515 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
516 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
517
518 // Make sure we don't crash in this case when we dump the status. We don't
519 // care what the actual dumped value is.
520 oat_file_assistant.GetStatusDump();
Calin Juravle5f9a8012018-02-12 20:27:46 -0800521
522 VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
Richard Uhler2f27abd2017-01-31 14:02:34 +0000523}
524
525// Case: We have a DEX file and empty VDEX and ODEX files.
526TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
527 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
528 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
529 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
530
531 Copy(GetDexSrc1(), dex_location);
Richard Uhler5cd59292017-02-01 12:54:23 +0000532 ScratchFile vdex_file(vdex_location.c_str());
533 ScratchFile odex_file(odex_location.c_str());
Richard Uhler2f27abd2017-01-31 14:02:34 +0000534
535 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
536 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
537 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
538}
539
540// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
541// file.
542TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000543 if (IsExecutedAsRoot()) {
544 // We cannot simulate non writable locations when executed as root: b/38000545.
545 LOG(ERROR) << "Test skipped because it's running as root";
546 return;
547 }
Richard Uhler2f27abd2017-01-31 14:02:34 +0000548
549 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
550 std::string oat_location;
551 std::string error_msg;
552 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
553 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
554
555 Copy(GetDexSrc1(), dex_location);
556 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
557 ASSERT_EQ(0, unlink(oat_location.c_str()));
558
Calin Juravle357c66d2017-05-04 01:57:17 +0000559 ScopedNonWritable scoped_non_writable(dex_location);
560 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700561 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
562
Richard Uhler2f27abd2017-01-31 14:02:34 +0000563 // Even though the vdex file is up to date, because we don't have the oat
564 // file, we can't know that the vdex depends on the boot image and is up to
565 // date with respect to the boot image. Instead we must assume the vdex file
566 // depends on the boot image and is out of date with respect to the boot
567 // image.
568 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700569 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700570}
571
Andreas Gampe29d38e72016-03-23 15:31:51 +0000572// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700573// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
574// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000575TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000576 if (IsExecutedAsRoot()) {
577 // We cannot simulate non writable locations when executed as root: b/38000545.
578 LOG(ERROR) << "Test skipped because it's running as root";
579 return;
580 }
581
Andreas Gampe29d38e72016-03-23 15:31:51 +0000582 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
583 Copy(GetDexSrc1(), dex_location);
584 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
585
Calin Juravle357c66d2017-05-04 01:57:17 +0000586 ScopedNonWritable scoped_non_writable(dex_location);
587 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
588
Richard Uhlerd1472a22016-04-15 15:18:56 -0700589 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000590
591 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700592 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000593 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100594 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000595 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700596 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000597 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100598 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000599
600 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000601 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000602 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
603 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
604}
605
Richard Uhler66d874d2015-01-15 09:37:19 -0800606// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700607// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800608TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000609 if (IsExecutedAsRoot()) {
610 // We cannot simulate non writable locations when executed as root: b/38000545.
611 LOG(ERROR) << "Test skipped because it's running as root";
612 return;
613 }
614
Richard Uhler66d874d2015-01-15 09:37:19 -0800615 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
616 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000617 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800618
Calin Juravle357c66d2017-05-04 01:57:17 +0000619 ScopedNonWritable scoped_non_writable(dex_location);
620 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
621
Richard Uhlerd1472a22016-04-15 15:18:56 -0700622 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000623 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700624 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700625 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700626
627 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700628 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800629 ASSERT_TRUE(oat_file.get() != nullptr);
630 EXPECT_TRUE(oat_file->IsExecutable());
631 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700632 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
633 EXPECT_EQ(2u, dex_files.size());
634}
635
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000636// Case: We have a MultiDEX file where the non-main multdex entry is out of date.
Richard Uhler67ff7d12015-05-14 13:21:13 -0700637// Expect: The status is kDex2OatNeeded.
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000638TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000639 if (IsExecutedAsRoot()) {
640 // We cannot simulate non writable locations when executed as root: b/38000545.
641 LOG(ERROR) << "Test skipped because it's running as root";
642 return;
643 }
644
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000645 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
Richard Uhler67ff7d12015-05-14 13:21:13 -0700646
647 // Compile code for GetMultiDexSrc1.
648 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000649 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700650
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000651 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
Richard Uhler67ff7d12015-05-14 13:21:13 -0700652 // is out of date.
653 Copy(GetMultiDexSrc2(), dex_location);
654
Calin Juravle357c66d2017-05-04 01:57:17 +0000655 ScopedNonWritable scoped_non_writable(dex_location);
656 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
657
Richard Uhlerd1472a22016-04-15 15:18:56 -0700658 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000659 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700660 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700661 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700662}
663
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000664// Case: We have a stripped MultiDEX file where the non-main multidex entry is
665// out of date with respect to the odex file.
666TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
667 std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
668 std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
669
670 // Compile the oat from GetMultiDexSrc1.
671 Copy(GetMultiDexSrc1(), dex_location);
672 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
673
674 // Compile the odex from GetMultiDexSrc2, which has a different non-main
675 // dex checksum.
676 Copy(GetMultiDexSrc2(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100677 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000678
679 // Strip the dex file.
680 Copy(GetStrippedDexSrc1(), dex_location);
681
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700682 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable=*/false);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000683
684 // Because the dex file is stripped, the odex file is considered the source
685 // of truth for the dex checksums. The oat file should be considered
686 // unusable.
687 std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
688 ASSERT_TRUE(best_file.get() != nullptr);
689 EXPECT_EQ(best_file->GetLocation(), odex_location);
690 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
691 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
692 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
693}
694
Richard Uhler03bc6592016-11-22 09:42:04 +0000695// Case: We have a DEX file and an OAT file out of date with respect to the
696// dex checksum.
697TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000698 if (IsExecutedAsRoot()) {
699 // We cannot simulate non writable locations when executed as root: b/38000545.
700 LOG(ERROR) << "Test skipped because it's running as root";
701 return;
702 }
703
Richard Uhler03bc6592016-11-22 09:42:04 +0000704 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800705
706 // We create a dex, generate an oat for it, then overwrite the dex with a
707 // different dex to make the oat out of date.
708 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000709 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800710 Copy(GetDexSrc2(), dex_location);
711
Calin Juravle357c66d2017-05-04 01:57:17 +0000712 ScopedNonWritable scoped_non_writable(dex_location);
713 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
714
Richard Uhlerd1472a22016-04-15 15:18:56 -0700715 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000716 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100717 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000718 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000719 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800720
721 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000722 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
723 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
724 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
725}
726
Richard Uhler2f27abd2017-01-31 14:02:34 +0000727// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
728// to the dex checksum, but no ODEX file.
729TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000730 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000731 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000732
733 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000734 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
735 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000736 Copy(GetDexSrc2(), dex_location);
737
Calin Juravle357c66d2017-05-04 01:57:17 +0000738 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000739
740 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
741 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
742}
743
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000744// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
745// is out of date and there is no corresponding ODEX file.
746TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000747 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000748 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000749
750 Copy(GetMultiDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000751 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
752 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000753 Copy(GetMultiDexSrc2(), dex_location);
754
Calin Juravle357c66d2017-05-04 01:57:17 +0000755 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000756
757 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
758 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
759}
760
Richard Uhler03bc6592016-11-22 09:42:04 +0000761// Case: We have a DEX file and an OAT file out of date with respect to the
762// boot image.
763TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000764 if (IsExecutedAsRoot()) {
765 // We cannot simulate non writable locations when executed as root: b/38000545.
766 LOG(ERROR) << "Test skipped because it's running as root";
767 return;
768 }
769
Richard Uhler03bc6592016-11-22 09:42:04 +0000770 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
771
772 Copy(GetDexSrc1(), dex_location);
773 GenerateOatForTest(dex_location.c_str(),
774 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700775 /* with_alternate_image= */ true);
Richard Uhler03bc6592016-11-22 09:42:04 +0000776
Calin Juravle357c66d2017-05-04 01:57:17 +0000777 ScopedNonWritable scoped_non_writable(dex_location);
778 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
779
Richard Uhler03bc6592016-11-22 09:42:04 +0000780 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000781 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100782 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000783 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100784 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000785 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000786 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
787
788 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
789 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
790 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
791 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
792}
793
794// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
795// respect to the boot image.
796// It shouldn't matter that the OAT file is out of date, because it is
797// verify-at-runtime.
798TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000799 if (IsExecutedAsRoot()) {
800 // We cannot simulate non writable locations when executed as root: b/38000545.
801 LOG(ERROR) << "Test skipped because it's running as root";
802 return;
803 }
804
Richard Uhler03bc6592016-11-22 09:42:04 +0000805 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
806
807 Copy(GetDexSrc1(), dex_location);
808 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100809 CompilerFilter::kExtract,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700810 /* with_alternate_image= */ true);
Richard Uhler03bc6592016-11-22 09:42:04 +0000811
Calin Juravle357c66d2017-05-04 01:57:17 +0000812 ScopedNonWritable scoped_non_writable(dex_location);
813 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
814
Richard Uhler03bc6592016-11-22 09:42:04 +0000815 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
816 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100817 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000818 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100819 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler03bc6592016-11-22 09:42:04 +0000820
821 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
822 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
823 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700824 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800825}
826
827// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800828TEST_F(OatFileAssistantTest, DexOdexNoOat) {
829 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700830 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800831
832 // Create the dex and odex files
833 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000834 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800835
836 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700837 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800838
Andreas Gampe29d38e72016-03-23 15:31:51 +0000839 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100840 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Vladimir Markoe0669322018-09-03 15:44:54 +0100841 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000842 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800843
844 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Vladimir Markoe0669322018-09-03 15:44:54 +0100845 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000846 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700847 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700848
849 // We should still be able to get the non-executable odex file to run from.
850 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
851 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800852}
853
Richard Uhler5923b522016-12-08 09:48:01 +0000854// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800855TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
856 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700857 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800858
859 // Create the dex and odex files
860 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100861 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800862
863 // Strip the dex file
864 Copy(GetStrippedDexSrc1(), dex_location);
865
866 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700867 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800868
Richard Uhler5923b522016-12-08 09:48:01 +0000869 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000870 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800871
872 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000873 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000874 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700875 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800876
Richard Uhler66d874d2015-01-15 09:37:19 -0800877 // Verify we can load the dex files from it.
878 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
879 ASSERT_TRUE(oat_file.get() != nullptr);
880 EXPECT_TRUE(oat_file->IsExecutable());
881 std::vector<std::unique_ptr<const DexFile>> dex_files;
882 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
883 EXPECT_EQ(1u, dex_files.size());
884}
885
Richard Uhler5923b522016-12-08 09:48:01 +0000886// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800887TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
888 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700889 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800890
891 // Create the oat file from a different dex file so it looks out of date.
892 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000893 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800894
895 // Create the odex file
896 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100897 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800898
899 // Strip the dex file.
900 Copy(GetStrippedDexSrc1(), dex_location);
901
902 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700903 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800904
Andreas Gampe29d38e72016-03-23 15:31:51 +0000905 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100906 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000907 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
908 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Nicolas Geoffray08e9eed2017-04-25 17:36:51 +0100909 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, // Compiling from the .vdex file
Andreas Gampe29d38e72016-03-23 15:31:51 +0000910 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800911
912 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000913 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
914 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700915 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800916
917 // Verify we can load the dex files from it.
918 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
919 ASSERT_TRUE(oat_file.get() != nullptr);
920 EXPECT_TRUE(oat_file->IsExecutable());
921 std::vector<std::unique_ptr<const DexFile>> dex_files;
922 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
923 EXPECT_EQ(1u, dex_files.size());
924}
925
Richard Uhler9b994ea2015-06-24 08:44:19 -0700926// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
927// OAT file. Expect: The status is kNoDexOptNeeded.
928TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
929 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
930
931 Copy(GetStrippedDexSrc1(), dex_location);
932
933 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700934 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700935
Andreas Gampe29d38e72016-03-23 15:31:51 +0000936 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
937 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
938 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100939 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000940 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100941 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700942
943 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000944 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
945 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700946 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
947
Andreas Gampe29d38e72016-03-23 15:31:51 +0000948 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
949 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700950
951 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000952 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
953 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700954 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
955}
956
Vladimir Markoe0669322018-09-03 15:44:54 +0100957// Case: We have a DEX file, an ODEX file and an OAT file.
958// Expect: It shouldn't crash. We should load the odex file executable.
Richard Uhler66d874d2015-01-15 09:37:19 -0800959TEST_F(OatFileAssistantTest, OdexOatOverlap) {
960 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700961 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800962
Calin Juravle357c66d2017-05-04 01:57:17 +0000963 // Create the dex, the odex and the oat files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800964 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000965 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Vladimir Markoe0669322018-09-03 15:44:54 +0100966 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800967
968 // Verify things don't go bad.
Calin Juravle357c66d2017-05-04 01:57:17 +0000969 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800970
Vladimir Markoe0669322018-09-03 15:44:54 +0100971 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
972 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800973
974 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Vladimir Markoe0669322018-09-03 15:44:54 +0100975 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
976 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700977 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800978
Richard Uhler66d874d2015-01-15 09:37:19 -0800979 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
980 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700981
Vladimir Markoe0669322018-09-03 15:44:54 +0100982 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -0800983 std::vector<std::unique_ptr<const DexFile>> dex_files;
984 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
985 EXPECT_EQ(1u, dex_files.size());
986}
987
Andreas Gampe29d38e72016-03-23 15:31:51 +0000988// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
989// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
990TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
991 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
992 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000993
994 // Create the dex and odex files
995 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100996 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000997
998 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700999 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +00001000
Andreas Gampe29d38e72016-03-23 15:31:51 +00001001 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001002 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +00001003 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001004 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +00001005
1006 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +00001007 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +00001008 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +00001009 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
1010}
1011
Richard Uhler66d874d2015-01-15 09:37:19 -08001012// Case: We have a DEX file and up-to-date OAT file for it.
1013// Expect: We should load an executable dex file.
1014TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001015 if (IsExecutedAsRoot()) {
1016 // We cannot simulate non writable locations when executed as root: b/38000545.
1017 LOG(ERROR) << "Test skipped because it's running as root";
1018 return;
1019 }
1020
Richard Uhler66d874d2015-01-15 09:37:19 -08001021 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
1022
1023 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001024 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001025
Calin Juravle357c66d2017-05-04 01:57:17 +00001026 ScopedNonWritable scoped_non_writable(dex_location);
1027 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1028
Richard Uhler66d874d2015-01-15 09:37:19 -08001029 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001030 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001031
1032 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1033 ASSERT_TRUE(oat_file.get() != nullptr);
1034 EXPECT_TRUE(oat_file->IsExecutable());
1035 std::vector<std::unique_ptr<const DexFile>> dex_files;
1036 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1037 EXPECT_EQ(1u, dex_files.size());
1038}
1039
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001040// Case: We have a DEX file and up-to-date quicken OAT file for it.
Andreas Gampe29d38e72016-03-23 15:31:51 +00001041// Expect: We should still load the oat file as executable.
1042TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001043 if (IsExecutedAsRoot()) {
1044 // We cannot simulate non writable locations when executed as root: b/38000545.
1045 LOG(ERROR) << "Test skipped because it's running as root";
1046 return;
1047 }
1048
Andreas Gampe29d38e72016-03-23 15:31:51 +00001049 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
1050
1051 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001052 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001053
Calin Juravle357c66d2017-05-04 01:57:17 +00001054 ScopedNonWritable scoped_non_writable(dex_location);
1055 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1056
Andreas Gampe29d38e72016-03-23 15:31:51 +00001057 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001058 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001059
1060 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1061 ASSERT_TRUE(oat_file.get() != nullptr);
1062 EXPECT_TRUE(oat_file->IsExecutable());
1063 std::vector<std::unique_ptr<const DexFile>> dex_files;
1064 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1065 EXPECT_EQ(1u, dex_files.size());
1066}
1067
1068// Case: We have a DEX file and up-to-date OAT file for it.
1069// Expect: Loading non-executable should load the oat non-executable.
1070TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001071 if (IsExecutedAsRoot()) {
1072 // We cannot simulate non writable locations when executed as root: b/38000545.
1073 LOG(ERROR) << "Test skipped because it's running as root";
1074 return;
1075 }
1076
Richard Uhler66d874d2015-01-15 09:37:19 -08001077 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
1078
1079 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +00001080
1081 ScopedNonWritable scoped_non_writable(dex_location);
1082 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1083
Andreas Gampe29d38e72016-03-23 15:31:51 +00001084 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001085
1086 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001087 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001088
1089 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1090 ASSERT_TRUE(oat_file.get() != nullptr);
1091 EXPECT_FALSE(oat_file->IsExecutable());
1092 std::vector<std::unique_ptr<const DexFile>> dex_files;
1093 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1094 EXPECT_EQ(1u, dex_files.size());
1095}
1096
Richard Uhler66d874d2015-01-15 09:37:19 -08001097// Turn an absolute path into a path relative to the current working
1098// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -08001099static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001100 char buf[MAXPATHLEN];
1101 std::string cwd = getcwd(buf, MAXPATHLEN);
1102
1103 // Split the target and cwd paths into components.
1104 std::vector<std::string> target_path;
1105 std::vector<std::string> cwd_path;
1106 Split(target, '/', &target_path);
1107 Split(cwd, '/', &cwd_path);
1108
1109 // Reverse the path components, so we can use pop_back().
1110 std::reverse(target_path.begin(), target_path.end());
1111 std::reverse(cwd_path.begin(), cwd_path.end());
1112
1113 // Drop the common prefix of the paths. Because we reversed the path
1114 // components, this becomes the common suffix of target_path and cwd_path.
1115 while (!target_path.empty() && !cwd_path.empty()
1116 && target_path.back() == cwd_path.back()) {
1117 target_path.pop_back();
1118 cwd_path.pop_back();
1119 }
1120
1121 // For each element of the remaining cwd_path, add '..' to the beginning
1122 // of the target path. Because we reversed the path components, we add to
1123 // the end of target_path.
1124 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1125 target_path.push_back("..");
1126 }
1127
1128 // Reverse again to get the right path order, and join to get the result.
1129 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001130 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001131}
1132
1133// Case: Non-absolute path to Dex location.
1134// Expect: Not sure, but it shouldn't crash.
1135TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1136 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1137 Copy(GetDexSrc1(), abs_dex_location);
1138
1139 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -07001140 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001141
1142 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001143 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001144 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001145 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1146 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001147}
1148
1149// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001150// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001151TEST_F(OatFileAssistantTest, ShortDexLocation) {
1152 std::string dex_location = "/xx";
1153
Richard Uhlerd1472a22016-04-15 15:18:56 -07001154 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001155
1156 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001157 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1158 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001159 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1160 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001161 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001162}
1163
1164// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001165// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001166TEST_F(OatFileAssistantTest, LongDexExtension) {
1167 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1168 Copy(GetDexSrc1(), dex_location);
1169
Richard Uhlerd1472a22016-04-15 15:18:56 -07001170 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001171
Richard Uhler7225a8d2016-11-22 10:12:03 +00001172 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001173 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001174
1175 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001176 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1177 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001178}
1179
1180// A task to generate a dex location. Used by the RaceToGenerate test.
1181class RaceGenerateTask : public Task {
1182 public:
Vladimir Markob9c29f62019-03-20 14:22:51 +00001183 RaceGenerateTask(OatFileAssistantTest& test,
1184 const std::string& dex_location,
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001185 const std::string& oat_location,
1186 Mutex* lock)
Vladimir Markob9c29f62019-03-20 14:22:51 +00001187 : test_(test),
1188 dex_location_(dex_location),
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001189 oat_location_(oat_location),
1190 lock_(lock),
1191 loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001192 {}
1193
Andreas Gampefa6a1b02018-09-07 08:11:55 -07001194 void Run(Thread* self ATTRIBUTE_UNUSED) override {
Richard Uhler66d874d2015-01-15 09:37:19 -08001195 // Load the dex files, and save a pointer to the loaded oat file, so that
1196 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001197 std::vector<std::unique_ptr<const DexFile>> dex_files;
1198 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001199 const OatFile* oat_file = nullptr;
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001200 {
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001201 MutexLock mu(Thread::Current(), *lock_);
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001202 // Create the oat file.
1203 std::vector<std::string> args;
1204 args.push_back("--dex-file=" + dex_location_);
1205 args.push_back("--oat-file=" + oat_location_);
1206 std::string error_msg;
Vladimir Markob9c29f62019-03-20 14:22:51 +00001207 ASSERT_TRUE(test_.Dex2Oat(args, &error_msg)) << error_msg;
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001208 }
1209
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001210 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1211 dex_location_.c_str(),
Jeff Hao0cb17282017-07-12 14:51:49 -07001212 Runtime::Current()->GetSystemClassLoader(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001213 /*dex_elements=*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001214 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001215 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001216 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001217 if (dex_files[0]->GetOatDexFile() != nullptr) {
1218 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
1219 }
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001220 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001221 }
1222
1223 const OatFile* GetLoadedOatFile() const {
1224 return loaded_oat_file_;
1225 }
1226
1227 private:
Vladimir Markob9c29f62019-03-20 14:22:51 +00001228 OatFileAssistantTest& test_;
Richard Uhler66d874d2015-01-15 09:37:19 -08001229 std::string dex_location_;
1230 std::string oat_location_;
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001231 Mutex* lock_;
Richard Uhler66d874d2015-01-15 09:37:19 -08001232 const OatFile* loaded_oat_file_;
1233};
1234
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001235// Test the case where dex2oat invocations race with multiple processes trying to
1236// load the oat file.
Richard Uhler66d874d2015-01-15 09:37:19 -08001237TEST_F(OatFileAssistantTest, RaceToGenerate) {
1238 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001239 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001240
Jeff Hao0cb17282017-07-12 14:51:49 -07001241 // Start the runtime to initialize the system's class loader.
1242 Thread::Current()->TransitionFromSuspendedToRunnable();
1243 runtime_->Start();
1244
Richard Uhler66d874d2015-01-15 09:37:19 -08001245 // We use the lib core dex file, because it's large, and hopefully should
1246 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001247 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001248
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001249 const size_t kNumThreads = 32;
Richard Uhler66d874d2015-01-15 09:37:19 -08001250 Thread* self = Thread::Current();
1251 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1252 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001253 Mutex lock("RaceToGenerate");
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001254 for (size_t i = 0; i < kNumThreads; i++) {
Vladimir Markob9c29f62019-03-20 14:22:51 +00001255 std::unique_ptr<RaceGenerateTask> task(
1256 new RaceGenerateTask(*this, dex_location, oat_location, &lock));
Richard Uhler66d874d2015-01-15 09:37:19 -08001257 thread_pool.AddTask(self, task.get());
1258 tasks.push_back(std::move(task));
1259 }
1260 thread_pool.StartWorkers(self);
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001261 thread_pool.Wait(self, /* do_work= */ true, /* may_hold_locks= */ false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001262
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001263 // Verify that tasks which got an oat file got a unique one.
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001264 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001265 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001266 const OatFile* oat_file = task->GetLoadedOatFile();
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001267 if (oat_file != nullptr) {
1268 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1269 oat_files.insert(oat_file);
1270 }
Richard Uhler66d874d2015-01-15 09:37:19 -08001271 }
1272}
1273
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001274// Case: We have a DEX file and an ODEX file, and no OAT file,
Vladimir Markoe0669322018-09-03 15:44:54 +01001275// Expect: We should load the odex file executable.
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001276TEST_F(DexoptTest, LoadDexOdexNoOat) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001277 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001278 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001279
1280 // Create the dex and odex files
1281 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001282 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001283
1284 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001285 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001286
1287 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1288 ASSERT_TRUE(oat_file.get() != nullptr);
Vladimir Markoe0669322018-09-03 15:44:54 +01001289 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -08001290 std::vector<std::unique_ptr<const DexFile>> dex_files;
1291 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1292 EXPECT_EQ(1u, dex_files.size());
1293}
1294
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001295// Case: We have a MultiDEX file and an ODEX file, and no OAT file.
Vladimir Markoe0669322018-09-03 15:44:54 +01001296// Expect: We should load the odex file executable.
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001297TEST_F(DexoptTest, LoadMultiDexOdexNoOat) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001298 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001299 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001300
1301 // Create the dex and odex files
1302 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001303 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001304
1305 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001306 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001307
1308 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1309 ASSERT_TRUE(oat_file.get() != nullptr);
Vladimir Markoe0669322018-09-03 15:44:54 +01001310 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -08001311 std::vector<std::unique_ptr<const DexFile>> dex_files;
1312 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1313 EXPECT_EQ(2u, dex_files.size());
1314}
1315
Richard Uhlerb81881d2016-04-19 13:08:04 -07001316TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001317 std::string error_msg;
1318 std::string odex_file;
1319
Richard Uhlerb81881d2016-04-19 13:08:04 -07001320 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001321 "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001322 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001323
Richard Uhlerb81881d2016-04-19 13:08:04 -07001324 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001325 "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001326 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001327
Richard Uhlerb81881d2016-04-19 13:08:04 -07001328 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001329 "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001330 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001331 "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001332}
1333
Richard Uhler23cedd22015-04-08 13:17:29 -07001334// Verify the dexopt status values from dalvik.system.DexFile
1335// match the OatFileAssistant::DexOptStatus values.
1336TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001337 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1338 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1339 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1340 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1341 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001342 };
1343
Richard Uhler23cedd22015-04-08 13:17:29 -07001344 ScopedObjectAccess soa(Thread::Current());
1345 StackHandleScope<1> hs(soa.Self());
1346 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1347 Handle<mirror::Class> dexfile(
1348 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
Andreas Gampefa4333d2017-02-14 11:10:34 -08001349 ASSERT_FALSE(dexfile == nullptr);
Richard Uhler23cedd22015-04-08 13:17:29 -07001350 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1351
Richard Uhler7225a8d2016-11-22 10:12:03 +00001352 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1353 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001354 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001355 ASSERT_FALSE(art_field == nullptr);
1356 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1357 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1358 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001359}
Richard Uhler66d874d2015-01-15 09:37:19 -08001360
Calin Juravle44e5efa2017-09-12 00:54:26 -07001361TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
1362 std::string dex_location = GetScratchDir() + "/TestDex.jar";
Calin Juravleaf322422020-02-11 13:45:53 -08001363 std::string odex_location = GetOdexDir() + "/TestDex.odex";
1364
Calin Juravle44e5efa2017-09-12 00:54:26 -07001365 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1366 Copy(GetDexSrc1(), dex_location);
1367 Copy(GetDexSrc2(), context_location);
1368
Calin Juravle44e5efa2017-09-12 00:54:26 -07001369 std::string context_str = "PCL[" + context_location + "]";
Calin Juravleaf322422020-02-11 13:45:53 -08001370
Calin Juravle44e5efa2017-09-12 00:54:26 -07001371 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1372 ASSERT_TRUE(context != nullptr);
1373 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1374
Calin Juravleaf322422020-02-11 13:45:53 -08001375 std::string error_msg;
1376 std::vector<std::string> args;
1377 args.push_back("--dex-file=" + dex_location);
1378 args.push_back("--oat-file=" + odex_location);
1379 args.push_back("--class-loader-context=" + context_str);
1380 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
1381
Calin Juravle44e5efa2017-09-12 00:54:26 -07001382 // Update the context by overriding the jar file.
1383 Copy(GetMultiDexSrc2(), context_location);
1384 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1385 ASSERT_TRUE(updated_context != nullptr);
Calin Juravleaf322422020-02-11 13:45:53 -08001386
1387 {
1388 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1389 // DexOptNeeded should advise compilation from scratch when the context changes.
1390 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
1391 oat_file_assistant.GetDexOptNeeded(
1392 CompilerFilter::kDefaultCompilerFilter,
1393 /* profile_changed= */ false,
1394 /* downgrade= */ false,
1395 updated_context.get()));
1396 }
1397 {
1398 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1399 // Now check that DexOptNeeded does not advise compilation if we only extracted the file.
1400 args.push_back("--compiler-filter=extract");
1401 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
1402 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1403 oat_file_assistant.GetDexOptNeeded(
1404 CompilerFilter::kExtract,
1405 /* profile_changed= */ false,
1406 /* downgrade= */ false,
1407 updated_context.get()));
1408 }
Nicolas Geoffray29742602017-12-14 10:09:03 +00001409}
1410
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001411// Test that GetLocation of a dex file is the same whether the dex
1412// filed is backed by an oat file or not.
1413TEST_F(OatFileAssistantTest, GetDexLocation) {
1414 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1415 std::string oat_location = GetOdexDir() + "/TestDex.odex";
1416
1417 // Start the runtime to initialize the system's class loader.
1418 Thread::Current()->TransitionFromSuspendedToRunnable();
1419 runtime_->Start();
1420
1421 Copy(GetDexSrc1(), dex_location);
1422
1423 std::vector<std::unique_ptr<const DexFile>> dex_files;
1424 std::vector<std::string> error_msgs;
1425 const OatFile* oat_file = nullptr;
1426
1427 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1428 dex_location.c_str(),
1429 Runtime::Current()->GetSystemClassLoader(),
1430 /*dex_elements=*/nullptr,
1431 &oat_file,
1432 &error_msgs);
Vladimir Markob7bf8432019-12-03 13:18:50 +00001433 ASSERT_EQ(dex_files.size(), 1u) << android::base::Join(error_msgs, "\n");
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001434 EXPECT_EQ(oat_file, nullptr);
1435 std::string stored_dex_location = dex_files[0]->GetLocation();
1436 {
1437 // Create the oat file.
1438 std::vector<std::string> args;
1439 args.push_back("--dex-file=" + dex_location);
1440 args.push_back("--dex-location=TestDex.jar");
1441 args.push_back("--oat-file=" + oat_location);
1442 std::string error_msg;
1443 ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
1444 }
1445 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1446 dex_location.c_str(),
1447 Runtime::Current()->GetSystemClassLoader(),
1448 /*dex_elements=*/nullptr,
1449 &oat_file,
1450 &error_msgs);
Vladimir Markob7bf8432019-12-03 13:18:50 +00001451 ASSERT_EQ(dex_files.size(), 1u) << android::base::Join(error_msgs, "\n");
1452 ASSERT_NE(oat_file, nullptr);
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001453 std::string oat_stored_dex_location = dex_files[0]->GetLocation();
1454 EXPECT_EQ(oat_stored_dex_location, stored_dex_location);
1455}
1456
1457// Test that a dex file on the platform location gets the right hiddenapi domain,
1458// regardless of whether it has a backing oat file.
1459TEST_F(OatFileAssistantTest, SystemFrameworkDir) {
1460 std::string filebase = "OatFileAssistantTestSystemFrameworkDir";
1461 std::string dex_location = GetAndroidRoot() + "/framework/" + filebase + ".jar";
1462 Copy(GetDexSrc1(), dex_location);
1463
1464 std::string odex_dir = GetAndroidRoot() + "/framework/oat/";
1465 mkdir(odex_dir.c_str(), 0700);
1466 odex_dir = odex_dir + std::string(GetInstructionSetString(kRuntimeISA));
1467 mkdir(odex_dir.c_str(), 0700);
1468 std::string oat_location = odex_dir + "/" + filebase + ".odex";
1469 // Clean up in case previous run crashed.
1470 remove(oat_location.c_str());
1471
1472 // Start the runtime to initialize the system's class loader.
1473 Thread::Current()->TransitionFromSuspendedToRunnable();
1474 runtime_->Start();
1475
1476 std::vector<std::unique_ptr<const DexFile>> dex_files_first;
1477 std::vector<std::unique_ptr<const DexFile>> dex_files_second;
1478 std::vector<std::string> error_msgs;
1479 const OatFile* oat_file = nullptr;
1480
1481 dex_files_first = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1482 dex_location.c_str(),
1483 Runtime::Current()->GetSystemClassLoader(),
1484 /*dex_elements=*/nullptr,
1485 &oat_file,
1486 &error_msgs);
Vladimir Markob7bf8432019-12-03 13:18:50 +00001487 ASSERT_EQ(dex_files_first.size(), 1u) << android::base::Join(error_msgs, "\n");
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001488 EXPECT_EQ(oat_file, nullptr) << dex_location;
1489 EXPECT_EQ(dex_files_first[0]->GetOatDexFile(), nullptr);
1490
1491 // Register the dex file to get a domain.
1492 {
1493 ScopedObjectAccess soa(Thread::Current());
1494 Runtime::Current()->GetClassLinker()->RegisterDexFile(
1495 *dex_files_first[0],
1496 soa.Decode<mirror::ClassLoader>(Runtime::Current()->GetSystemClassLoader()));
1497 }
1498 std::string stored_dex_location = dex_files_first[0]->GetLocation();
1499 EXPECT_EQ(dex_files_first[0]->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
1500 {
1501 // Create the oat file.
1502 std::vector<std::string> args;
1503 args.push_back("--dex-file=" + dex_location);
1504 args.push_back("--dex-location=" + filebase + ".jar");
1505 args.push_back("--oat-file=" + oat_location);
1506 std::string error_msg;
1507 ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
1508 }
1509 dex_files_second = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1510 dex_location.c_str(),
1511 Runtime::Current()->GetSystemClassLoader(),
1512 /*dex_elements=*/nullptr,
1513 &oat_file,
1514 &error_msgs);
Vladimir Markob7bf8432019-12-03 13:18:50 +00001515 ASSERT_EQ(dex_files_second.size(), 1u) << android::base::Join(error_msgs, "\n");
1516 ASSERT_NE(oat_file, nullptr);
Nicolas Geoffraye3e0f702019-03-12 07:02:02 +00001517 EXPECT_NE(dex_files_second[0]->GetOatDexFile(), nullptr);
1518 EXPECT_NE(dex_files_second[0]->GetOatDexFile()->GetOatFile(), nullptr);
1519
1520 // Register the dex file to get a domain.
1521 {
1522 ScopedObjectAccess soa(Thread::Current());
1523 Runtime::Current()->GetClassLinker()->RegisterDexFile(
1524 *dex_files_second[0],
1525 soa.Decode<mirror::ClassLoader>(Runtime::Current()->GetSystemClassLoader()));
1526 }
1527 std::string oat_stored_dex_location = dex_files_second[0]->GetLocation();
1528 EXPECT_EQ(oat_stored_dex_location, stored_dex_location);
1529 EXPECT_EQ(dex_files_second[0]->GetHiddenapiDomain(), hiddenapi::Domain::kPlatform);
1530 EXPECT_EQ(0, remove(oat_location.c_str()));
1531}
1532
Richard Uhler66d874d2015-01-15 09:37:19 -08001533// TODO: More Tests:
1534// * Test class linker falls back to unquickened dex for DexNoOat
1535// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001536// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001537// * Test for status of oat while oat is being generated (how?)
1538// * Test case where 32 and 64 bit boot class paths differ,
1539// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1540// 64 bit boot class paths.
1541// * Test unexpected scenarios (?):
1542// - Dex is stripped, don't have odex.
1543// - Oat file corrupted after status check, before reload unexecutable
1544// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001545} // namespace art