blob: 521e419d2fc977805ad6d8be53056e4adb35011b [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"
Calin Juravle27e0d1f2017-07-26 00:16:07 -070037#include "oat_file.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070038#include "oat_file_manager.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070039#include "scoped_thread_state_change-inl.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070040#include "thread-current-inl.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080041
42namespace art {
43
Calin Juravle5f9a8012018-02-12 20:27:46 -080044class OatFileAssistantTest : public DexoptTest {
45 public:
46 void VerifyOptimizationStatus(const std::string& file,
47 const std::string& expected_filter,
48 const std::string& expected_reason) {
49 std::string compilation_filter;
50 std::string compilation_reason;
51 OatFileAssistant::GetOptimizationStatus(
52 file, kRuntimeISA, &compilation_filter, &compilation_reason);
53
54 ASSERT_EQ(expected_filter, compilation_filter);
55 ASSERT_EQ(expected_reason, compilation_reason);
56 }
57
58 void VerifyOptimizationStatus(const std::string& file,
59 CompilerFilter::Filter expected_filter,
60 const std::string& expected_reason) {
61 VerifyOptimizationStatus(
62 file, CompilerFilter::NameOfFilter(expected_filter), expected_reason);
63 }
64};
Richard Uhler66d874d2015-01-15 09:37:19 -080065
Calin Juravle357c66d2017-05-04 01:57:17 +000066class ScopedNonWritable {
67 public:
68 explicit ScopedNonWritable(const std::string& dex_location) {
69 is_valid_ = false;
70 size_t pos = dex_location.rfind('/');
71 if (pos != std::string::npos) {
72 is_valid_ = true;
73 dex_parent_ = dex_location.substr(0, pos);
74 if (chmod(dex_parent_.c_str(), 0555) != 0) {
75 PLOG(ERROR) << "Could not change permissions on " << dex_parent_;
76 }
77 }
78 }
79
80 bool IsSuccessful() { return is_valid_ && (access(dex_parent_.c_str(), W_OK) != 0); }
81
82 ~ScopedNonWritable() {
83 if (is_valid_) {
84 if (chmod(dex_parent_.c_str(), 0777) != 0) {
85 PLOG(ERROR) << "Could not restore permissions on " << dex_parent_;
86 }
87 }
88 }
89
90 private:
91 std::string dex_parent_;
92 bool is_valid_;
93};
94
95static bool IsExecutedAsRoot() {
96 return geteuid() == 0;
97}
Calin Juravle36eb3132017-01-13 16:32:38 -080098
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +000099// Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
100// encoded dex locations.
101// Expect: The oat file status is kNoDexOptNeeded.
102TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
103 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
104 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
105
106 // Create the dex file
107 Copy(GetMultiDexSrc1(), dex_location);
108
109 // Create the oat file with relative encoded dex location.
110 std::vector<std::string> args = {
111 "--dex-file=" + dex_location,
112 "--dex-location=" + std::string("RelativeEncodedDexLocation.jar"),
113 "--oat-file=" + odex_location,
114 "--compiler-filter=speed"
115 };
116
117 std::string error_msg;
118 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
119
120 // Verify we can load both dex files.
121 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
122
123 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
124 ASSERT_TRUE(oat_file.get() != nullptr);
125 EXPECT_TRUE(oat_file->IsExecutable());
126 std::vector<std::unique_ptr<const DexFile>> dex_files;
127 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
128 EXPECT_EQ(2u, dex_files.size());
129}
130
131TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
132 std::string dex_location = GetScratchDir() + "/TestDex.jar";
133 std::string odex_location = GetOdexDir() + "/TestDex.odex";
134 std::string context_location = GetScratchDir() + "/ContextDex.jar";
135 Copy(GetDexSrc1(), dex_location);
136 Copy(GetDexSrc2(), context_location);
137
138 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
139
140 std::string context_str = "PCL[" + context_location + "]";
141 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
142 ASSERT_TRUE(context != nullptr);
143 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
144
145 std::string error_msg;
146 std::vector<std::string> args;
147 args.push_back("--dex-file=" + dex_location);
148 args.push_back("--oat-file=" + odex_location);
149 args.push_back("--class-loader-context=" + context_str);
150 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
151
152 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
153 EXPECT_NE(nullptr, oat_file.get());
154 EXPECT_EQ(context->EncodeContextForOatFile(""),
155 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
156}
157
158TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
159 std::string dex_location = GetScratchDir() + "/TestDex.jar";
160 std::string odex_location = GetOdexDir() + "/TestDex.odex";
161 std::string context_location = GetScratchDir() + "/ContextDex.jar";
162 Copy(GetDexSrc1(), dex_location);
163 Copy(GetDexSrc2(), context_location);
164
165 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
166
167 std::string context_str = "PCL[" + context_location + "]";
168 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
169 ASSERT_TRUE(context != nullptr);
170 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
171
172 std::string error_msg;
173 std::vector<std::string> args;
174 args.push_back("--dex-file=" + dex_location);
175 args.push_back("--oat-file=" + odex_location);
176 args.push_back("--class-loader-context=" + context_str);
177 ASSERT_TRUE(Dex2Oat(args, &error_msg)) << error_msg;
178
179 // A relative context simulates a dependent split context.
180 std::unique_ptr<ClassLoaderContext> relative_context =
181 ClassLoaderContext::Create("PCL[ContextDex.jar]");
182 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
183 oat_file_assistant.GetDexOptNeeded(
184 CompilerFilter::kDefaultCompilerFilter,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700185 /* profile_changed= */ false,
186 /* downgrade= */ false,
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +0000187 relative_context.get()));
188}
189
Richard Uhler66d874d2015-01-15 09:37:19 -0800190// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700191// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800192TEST_F(OatFileAssistantTest, DexNoOat) {
193 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
194 Copy(GetDexSrc1(), dex_location);
195
Richard Uhlerd1472a22016-04-15 15:18:56 -0700196 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800197
Richard Uhler7225a8d2016-11-22 10:12:03 +0000198 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100199 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000200 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100201 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000202 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000203 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000204 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000205 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800206
207 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000208 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
209 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700210 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800211
212 VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
Richard Uhler66d874d2015-01-15 09:37:19 -0800213}
214
215// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700216// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800217TEST_F(OatFileAssistantTest, NoDexNoOat) {
218 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
219
Richard Uhlerd1472a22016-04-15 15:18:56 -0700220 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800221
Andreas Gampe29d38e72016-03-23 15:31:51 +0000222 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
223 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700224 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
225
Richard Uhler9b994ea2015-06-24 08:44:19 -0700226 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800227 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
228 EXPECT_EQ(nullptr, oat_file.get());
229}
230
Vladimir Markoe0669322018-09-03 15:44:54 +0100231// Case: We have a DEX file and an ODEX file, but no OAT file.
232// Expect: The status is kNoDexOptNeeded.
Calin Juravle357c66d2017-05-04 01:57:17 +0000233TEST_F(OatFileAssistantTest, OdexUpToDate) {
234 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
235 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
236 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100237 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000238
239 // For the use of oat location by making the dex parent not writable.
240 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
241
242 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
243 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
244 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
245 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
246 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
247 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
248 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
249 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
250
251 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
252 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
253 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
254 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800255
256 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000257}
258
259// Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
260// file via a symlink.
Vladimir Markoe0669322018-09-03 15:44:54 +0100261// Expect: The status is kNoDexOptNeeded.
Calin Juravle357c66d2017-05-04 01:57:17 +0000262TEST_F(OatFileAssistantTest, OdexUpToDateSymLink) {
263 std::string scratch_dir = GetScratchDir();
264 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
265 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
266
267 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100268 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle357c66d2017-05-04 01:57:17 +0000269
270 // Now replace the dex location with a symlink.
271 std::string link = scratch_dir + "/link";
272 ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str()));
273 dex_location = link + "/OdexUpToDate.jar";
274
275 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
276
277 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
278 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
279 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
280 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
281 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
282 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
283 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
284 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
285
286 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
287 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
288 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
289 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
290}
291
Richard Uhler66d874d2015-01-15 09:37:19 -0800292// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700293// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800294TEST_F(OatFileAssistantTest, OatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000295 if (IsExecutedAsRoot()) {
296 // We cannot simulate non writable locations when executed as root: b/38000545.
297 LOG(ERROR) << "Test skipped because it's running as root";
298 return;
299 }
300
Richard Uhler66d874d2015-01-15 09:37:19 -0800301 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
302 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000303 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800304
Calin Juravle357c66d2017-05-04 01:57:17 +0000305 // For the use of oat location by making the dex parent not writable.
306 ScopedNonWritable scoped_non_writable(dex_location);
307 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
308
309 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
310
311 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
312 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
313 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
314 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
315 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
316 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
317 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
318 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
319
320 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
321 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
322 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
323 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800324
325 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "unknown");
Calin Juravle357c66d2017-05-04 01:57:17 +0000326}
327
Vladimir Markoe0669322018-09-03 15:44:54 +0100328// Case: Passing valid file descriptors of updated odex/vdex files along with the dex file.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700329// Expect: The status is kNoDexOptNeeded.
330TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) {
331 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
332 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
333 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
334
335 Copy(GetDexSrc1(), dex_location);
336 GenerateOatForTest(dex_location.c_str(),
337 odex_location.c_str(),
338 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700339 /* with_alternate_image= */ false);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700340
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700341 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY | O_CLOEXEC));
342 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY | O_CLOEXEC));
343 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700344
345 OatFileAssistant oat_file_assistant(dex_location.c_str(),
346 kRuntimeISA,
347 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000348 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700349 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700350 odex_fd.get(),
351 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700352 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
353 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
354 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
355 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
356 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
357 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
358 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
359 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
360
361 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
362 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
363 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
364 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
365}
366
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700367// Case: Passing invalid odex fd and valid vdex and zip fds.
368// Expect: The status should be kDex2OatForBootImage.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700369TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
370 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
371 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
372 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
373
374 Copy(GetDexSrc1(), dex_location);
375 GenerateOatForTest(dex_location.c_str(),
376 odex_location.c_str(),
377 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700378 /* with_alternate_image= */ false);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700379
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700380 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY | O_CLOEXEC));
381 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700382
383 OatFileAssistant oat_file_assistant(dex_location.c_str(),
384 kRuntimeISA,
385 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000386 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700387 vdex_fd.get(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700388 /* oat_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700389 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700390 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
391 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700392 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
393 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
394
395 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700396 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
397 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700398 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700399}
400
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700401// Case: Passing invalid vdex fd and valid odex and zip fds.
402// Expect: The status should be kDex2OatFromScratch.
403TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
404 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
405 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
406
407 Copy(GetDexSrc1(), dex_location);
408 GenerateOatForTest(dex_location.c_str(),
409 odex_location.c_str(),
410 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700411 /* with_alternate_image= */ false);
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700412
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700413 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY | O_CLOEXEC));
414 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700415
416 OatFileAssistant oat_file_assistant(dex_location.c_str(),
417 kRuntimeISA,
418 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000419 false,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700420 /* vdex_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700421 odex_fd.get(),
422 zip_fd.get());
423
424 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
425 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
426 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
427 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
428 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
429 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
430}
431
432// Case: Passing invalid vdex and odex fd with valid zip fd.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700433// Expect: The status is kDex2oatFromScratch.
434TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
435 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
436
437 Copy(GetDexSrc1(), dex_location);
438
Andreas Gampedfcd82c2018-10-16 20:22:37 -0700439 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY | O_CLOEXEC));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700440 OatFileAssistant oat_file_assistant(dex_location.c_str(),
441 kRuntimeISA,
442 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000443 false,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700444 /* vdex_fd= */ -1,
445 /* oat_fd= */ -1,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700446 zip_fd);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700447 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
448 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
449 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
450 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
451}
452
Richard Uhler2f27abd2017-01-31 14:02:34 +0000453// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
454// ODEX file.
455TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000456 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000457 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000458
Richard Uhler9a37efc2016-08-05 16:32:55 -0700459 Copy(GetDexSrc1(), dex_location);
460
Richard Uhler2f27abd2017-01-31 14:02:34 +0000461 // Generating and deleting the oat file should have the side effect of
462 // creating an up-to-date vdex file.
Calin Juravle357c66d2017-05-04 01:57:17 +0000463 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
464 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000465
Calin Juravle357c66d2017-05-04 01:57:17 +0000466 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000467
468 // Even though the vdex file is up to date, because we don't have the oat
469 // file, we can't know that the vdex depends on the boot image and is up to
470 // date with respect to the boot image. Instead we must assume the vdex file
471 // depends on the boot image and is out of date with respect to the boot
472 // image.
473 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
474 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
475
476 // Make sure we don't crash in this case when we dump the status. We don't
477 // care what the actual dumped value is.
478 oat_file_assistant.GetStatusDump();
Calin Juravle5f9a8012018-02-12 20:27:46 -0800479
480 VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
Richard Uhler2f27abd2017-01-31 14:02:34 +0000481}
482
483// Case: We have a DEX file and empty VDEX and ODEX files.
484TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
485 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
486 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
487 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
488
489 Copy(GetDexSrc1(), dex_location);
Richard Uhler5cd59292017-02-01 12:54:23 +0000490 ScratchFile vdex_file(vdex_location.c_str());
491 ScratchFile odex_file(odex_location.c_str());
Richard Uhler2f27abd2017-01-31 14:02:34 +0000492
493 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
494 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
495 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
496}
497
498// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
499// file.
500TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000501 if (IsExecutedAsRoot()) {
502 // We cannot simulate non writable locations when executed as root: b/38000545.
503 LOG(ERROR) << "Test skipped because it's running as root";
504 return;
505 }
Richard Uhler2f27abd2017-01-31 14:02:34 +0000506
507 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
508 std::string oat_location;
509 std::string error_msg;
510 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
511 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
512
513 Copy(GetDexSrc1(), dex_location);
514 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
515 ASSERT_EQ(0, unlink(oat_location.c_str()));
516
Calin Juravle357c66d2017-05-04 01:57:17 +0000517 ScopedNonWritable scoped_non_writable(dex_location);
518 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700519 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
520
Richard Uhler2f27abd2017-01-31 14:02:34 +0000521 // Even though the vdex file is up to date, because we don't have the oat
522 // file, we can't know that the vdex depends on the boot image and is up to
523 // date with respect to the boot image. Instead we must assume the vdex file
524 // depends on the boot image and is out of date with respect to the boot
525 // image.
526 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700527 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700528}
529
Andreas Gampe29d38e72016-03-23 15:31:51 +0000530// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700531// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
532// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000533TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000534 if (IsExecutedAsRoot()) {
535 // We cannot simulate non writable locations when executed as root: b/38000545.
536 LOG(ERROR) << "Test skipped because it's running as root";
537 return;
538 }
539
Andreas Gampe29d38e72016-03-23 15:31:51 +0000540 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
541 Copy(GetDexSrc1(), dex_location);
542 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
543
Calin Juravle357c66d2017-05-04 01:57:17 +0000544 ScopedNonWritable scoped_non_writable(dex_location);
545 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
546
Richard Uhlerd1472a22016-04-15 15:18:56 -0700547 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000548
549 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700550 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000551 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100552 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000553 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700554 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000555 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100556 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000557
558 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000559 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000560 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
561 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
562}
563
Richard Uhler66d874d2015-01-15 09:37:19 -0800564// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700565// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800566TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000567 if (IsExecutedAsRoot()) {
568 // We cannot simulate non writable locations when executed as root: b/38000545.
569 LOG(ERROR) << "Test skipped because it's running as root";
570 return;
571 }
572
Richard Uhler66d874d2015-01-15 09:37:19 -0800573 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
574 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000575 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800576
Calin Juravle357c66d2017-05-04 01:57:17 +0000577 ScopedNonWritable scoped_non_writable(dex_location);
578 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
579
Richard Uhlerd1472a22016-04-15 15:18:56 -0700580 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000581 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700582 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700583 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700584
585 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700586 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800587 ASSERT_TRUE(oat_file.get() != nullptr);
588 EXPECT_TRUE(oat_file->IsExecutable());
589 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700590 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
591 EXPECT_EQ(2u, dex_files.size());
592}
593
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000594// Case: We have a MultiDEX file where the non-main multdex entry is out of date.
Richard Uhler67ff7d12015-05-14 13:21:13 -0700595// Expect: The status is kDex2OatNeeded.
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000596TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000597 if (IsExecutedAsRoot()) {
598 // We cannot simulate non writable locations when executed as root: b/38000545.
599 LOG(ERROR) << "Test skipped because it's running as root";
600 return;
601 }
602
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000603 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
Richard Uhler67ff7d12015-05-14 13:21:13 -0700604
605 // Compile code for GetMultiDexSrc1.
606 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000607 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700608
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000609 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
Richard Uhler67ff7d12015-05-14 13:21:13 -0700610 // is out of date.
611 Copy(GetMultiDexSrc2(), dex_location);
612
Calin Juravle357c66d2017-05-04 01:57:17 +0000613 ScopedNonWritable scoped_non_writable(dex_location);
614 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
615
Richard Uhlerd1472a22016-04-15 15:18:56 -0700616 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000617 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700618 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700619 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700620}
621
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000622// Case: We have a stripped MultiDEX file where the non-main multidex entry is
623// out of date with respect to the odex file.
624TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
625 std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
626 std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
627
628 // Compile the oat from GetMultiDexSrc1.
629 Copy(GetMultiDexSrc1(), dex_location);
630 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
631
632 // Compile the odex from GetMultiDexSrc2, which has a different non-main
633 // dex checksum.
634 Copy(GetMultiDexSrc2(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100635 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000636
637 // Strip the dex file.
638 Copy(GetStrippedDexSrc1(), dex_location);
639
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700640 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable=*/false);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000641
642 // Because the dex file is stripped, the odex file is considered the source
643 // of truth for the dex checksums. The oat file should be considered
644 // unusable.
645 std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
646 ASSERT_TRUE(best_file.get() != nullptr);
647 EXPECT_EQ(best_file->GetLocation(), odex_location);
648 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
649 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
650 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
651}
652
Richard Uhler03bc6592016-11-22 09:42:04 +0000653// Case: We have a DEX file and an OAT file out of date with respect to the
654// dex checksum.
655TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000656 if (IsExecutedAsRoot()) {
657 // We cannot simulate non writable locations when executed as root: b/38000545.
658 LOG(ERROR) << "Test skipped because it's running as root";
659 return;
660 }
661
Richard Uhler03bc6592016-11-22 09:42:04 +0000662 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800663
664 // We create a dex, generate an oat for it, then overwrite the dex with a
665 // different dex to make the oat out of date.
666 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000667 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800668 Copy(GetDexSrc2(), dex_location);
669
Calin Juravle357c66d2017-05-04 01:57:17 +0000670 ScopedNonWritable scoped_non_writable(dex_location);
671 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
672
Richard Uhlerd1472a22016-04-15 15:18:56 -0700673 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000674 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100675 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000676 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000677 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800678
679 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000680 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
681 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
682 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
683}
684
Richard Uhler2f27abd2017-01-31 14:02:34 +0000685// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
686// to the dex checksum, but no ODEX file.
687TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000688 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000689 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000690
691 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000692 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
693 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000694 Copy(GetDexSrc2(), dex_location);
695
Calin Juravle357c66d2017-05-04 01:57:17 +0000696 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000697
698 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
699 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
700}
701
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000702// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
703// is out of date and there is no corresponding ODEX file.
704TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000705 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000706 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000707
708 Copy(GetMultiDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000709 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
710 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000711 Copy(GetMultiDexSrc2(), dex_location);
712
Calin Juravle357c66d2017-05-04 01:57:17 +0000713 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000714
715 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
716 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
717}
718
Richard Uhler03bc6592016-11-22 09:42:04 +0000719// Case: We have a DEX file and an OAT file out of date with respect to the
720// boot image.
721TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000722 if (IsExecutedAsRoot()) {
723 // We cannot simulate non writable locations when executed as root: b/38000545.
724 LOG(ERROR) << "Test skipped because it's running as root";
725 return;
726 }
727
Richard Uhler03bc6592016-11-22 09:42:04 +0000728 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
729
730 Copy(GetDexSrc1(), dex_location);
731 GenerateOatForTest(dex_location.c_str(),
732 CompilerFilter::kSpeed,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700733 /* with_alternate_image= */ true);
Richard Uhler03bc6592016-11-22 09:42:04 +0000734
Calin Juravle357c66d2017-05-04 01:57:17 +0000735 ScopedNonWritable scoped_non_writable(dex_location);
736 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
737
Richard Uhler03bc6592016-11-22 09:42:04 +0000738 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000739 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100740 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000741 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100742 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000743 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000744 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
745
746 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
747 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
748 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
749 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
750}
751
752// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
753// respect to the boot image.
754// It shouldn't matter that the OAT file is out of date, because it is
755// verify-at-runtime.
756TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000757 if (IsExecutedAsRoot()) {
758 // We cannot simulate non writable locations when executed as root: b/38000545.
759 LOG(ERROR) << "Test skipped because it's running as root";
760 return;
761 }
762
Richard Uhler03bc6592016-11-22 09:42:04 +0000763 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
764
765 Copy(GetDexSrc1(), dex_location);
766 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100767 CompilerFilter::kExtract,
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700768 /* with_alternate_image= */ true);
Richard Uhler03bc6592016-11-22 09:42:04 +0000769
Calin Juravle357c66d2017-05-04 01:57:17 +0000770 ScopedNonWritable scoped_non_writable(dex_location);
771 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
772
Richard Uhler03bc6592016-11-22 09:42:04 +0000773 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
774 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100775 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000776 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100777 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler03bc6592016-11-22 09:42:04 +0000778
779 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
780 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
781 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700782 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800783}
784
785// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800786TEST_F(OatFileAssistantTest, DexOdexNoOat) {
787 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700788 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800789
790 // Create the dex and odex files
791 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000792 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800793
794 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700795 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800796
Andreas Gampe29d38e72016-03-23 15:31:51 +0000797 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100798 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Vladimir Markoe0669322018-09-03 15:44:54 +0100799 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000800 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800801
802 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Vladimir Markoe0669322018-09-03 15:44:54 +0100803 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000804 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700805 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700806
807 // We should still be able to get the non-executable odex file to run from.
808 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
809 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800810}
811
Richard Uhler5923b522016-12-08 09:48:01 +0000812// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800813TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
814 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700815 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800816
817 // Create the dex and odex files
818 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100819 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800820
821 // Strip the dex file
822 Copy(GetStrippedDexSrc1(), dex_location);
823
824 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700825 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800826
Richard Uhler5923b522016-12-08 09:48:01 +0000827 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000828 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800829
830 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000831 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000832 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700833 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800834
Richard Uhler66d874d2015-01-15 09:37:19 -0800835 // Verify we can load the dex files from it.
836 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
837 ASSERT_TRUE(oat_file.get() != nullptr);
838 EXPECT_TRUE(oat_file->IsExecutable());
839 std::vector<std::unique_ptr<const DexFile>> dex_files;
840 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
841 EXPECT_EQ(1u, dex_files.size());
842}
843
Richard Uhler5923b522016-12-08 09:48:01 +0000844// 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 -0800845TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
846 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700847 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800848
849 // Create the oat file from a different dex file so it looks out of date.
850 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000851 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800852
853 // Create the odex file
854 Copy(GetDexSrc1(), dex_location);
Vladimir Markoe0669322018-09-03 15:44:54 +0100855 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800856
857 // Strip the dex file.
858 Copy(GetStrippedDexSrc1(), dex_location);
859
860 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700861 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800862
Andreas Gampe29d38e72016-03-23 15:31:51 +0000863 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100864 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000865 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
866 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Nicolas Geoffray08e9eed2017-04-25 17:36:51 +0100867 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, // Compiling from the .vdex file
Andreas Gampe29d38e72016-03-23 15:31:51 +0000868 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800869
870 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000871 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
872 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700873 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800874
875 // Verify we can load the dex files from it.
876 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
877 ASSERT_TRUE(oat_file.get() != nullptr);
878 EXPECT_TRUE(oat_file->IsExecutable());
879 std::vector<std::unique_ptr<const DexFile>> dex_files;
880 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
881 EXPECT_EQ(1u, dex_files.size());
882}
883
Richard Uhler9b994ea2015-06-24 08:44:19 -0700884// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
885// OAT file. Expect: The status is kNoDexOptNeeded.
886TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
887 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
888
889 Copy(GetStrippedDexSrc1(), dex_location);
890
891 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700892 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700893
Andreas Gampe29d38e72016-03-23 15:31:51 +0000894 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
895 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
896 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100897 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000898 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100899 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700900
901 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000902 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
903 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700904 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
905
Andreas Gampe29d38e72016-03-23 15:31:51 +0000906 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
907 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700908
909 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000910 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
911 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700912 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
913}
914
Vladimir Markoe0669322018-09-03 15:44:54 +0100915// Case: We have a DEX file, an ODEX file and an OAT file.
916// Expect: It shouldn't crash. We should load the odex file executable.
Richard Uhler66d874d2015-01-15 09:37:19 -0800917TEST_F(OatFileAssistantTest, OdexOatOverlap) {
918 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700919 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800920
Calin Juravle357c66d2017-05-04 01:57:17 +0000921 // Create the dex, the odex and the oat files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800922 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000923 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Vladimir Markoe0669322018-09-03 15:44:54 +0100924 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800925
926 // Verify things don't go bad.
Calin Juravle357c66d2017-05-04 01:57:17 +0000927 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800928
Vladimir Markoe0669322018-09-03 15:44:54 +0100929 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
930 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800931
932 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Vladimir Markoe0669322018-09-03 15:44:54 +0100933 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
934 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700935 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800936
Richard Uhler66d874d2015-01-15 09:37:19 -0800937 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
938 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700939
Vladimir Markoe0669322018-09-03 15:44:54 +0100940 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -0800941 std::vector<std::unique_ptr<const DexFile>> dex_files;
942 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
943 EXPECT_EQ(1u, dex_files.size());
944}
945
Andreas Gampe29d38e72016-03-23 15:31:51 +0000946// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
947// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
948TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
949 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
950 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000951
952 // Create the dex and odex files
953 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100954 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000955
956 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700957 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000958
Andreas Gampe29d38e72016-03-23 15:31:51 +0000959 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100960 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000961 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000962 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000963
964 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000965 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000966 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000967 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
968}
969
Richard Uhler66d874d2015-01-15 09:37:19 -0800970// Case: We have a DEX file and up-to-date OAT file for it.
971// Expect: We should load an executable dex file.
972TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000973 if (IsExecutedAsRoot()) {
974 // We cannot simulate non writable locations when executed as root: b/38000545.
975 LOG(ERROR) << "Test skipped because it's running as root";
976 return;
977 }
978
Richard Uhler66d874d2015-01-15 09:37:19 -0800979 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
980
981 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000982 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800983
Calin Juravle357c66d2017-05-04 01:57:17 +0000984 ScopedNonWritable scoped_non_writable(dex_location);
985 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
986
Richard Uhler66d874d2015-01-15 09:37:19 -0800987 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700988 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000989
990 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
991 ASSERT_TRUE(oat_file.get() != nullptr);
992 EXPECT_TRUE(oat_file->IsExecutable());
993 std::vector<std::unique_ptr<const DexFile>> dex_files;
994 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
995 EXPECT_EQ(1u, dex_files.size());
996}
997
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100998// Case: We have a DEX file and up-to-date quicken OAT file for it.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000999// Expect: We should still load the oat file as executable.
1000TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001001 if (IsExecutedAsRoot()) {
1002 // We cannot simulate non writable locations when executed as root: b/38000545.
1003 LOG(ERROR) << "Test skipped because it's running as root";
1004 return;
1005 }
1006
Andreas Gampe29d38e72016-03-23 15:31:51 +00001007 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
1008
1009 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001010 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001011
Calin Juravle357c66d2017-05-04 01:57:17 +00001012 ScopedNonWritable scoped_non_writable(dex_location);
1013 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1014
Andreas Gampe29d38e72016-03-23 15:31:51 +00001015 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001016 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001017
1018 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1019 ASSERT_TRUE(oat_file.get() != nullptr);
1020 EXPECT_TRUE(oat_file->IsExecutable());
1021 std::vector<std::unique_ptr<const DexFile>> dex_files;
1022 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1023 EXPECT_EQ(1u, dex_files.size());
1024}
1025
1026// Case: We have a DEX file and up-to-date OAT file for it.
1027// Expect: Loading non-executable should load the oat non-executable.
1028TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001029 if (IsExecutedAsRoot()) {
1030 // We cannot simulate non writable locations when executed as root: b/38000545.
1031 LOG(ERROR) << "Test skipped because it's running as root";
1032 return;
1033 }
1034
Richard Uhler66d874d2015-01-15 09:37:19 -08001035 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
1036
1037 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +00001038
1039 ScopedNonWritable scoped_non_writable(dex_location);
1040 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1041
Andreas Gampe29d38e72016-03-23 15:31:51 +00001042 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001043
1044 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001045 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001046
1047 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1048 ASSERT_TRUE(oat_file.get() != nullptr);
1049 EXPECT_FALSE(oat_file->IsExecutable());
1050 std::vector<std::unique_ptr<const DexFile>> dex_files;
1051 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1052 EXPECT_EQ(1u, dex_files.size());
1053}
1054
Richard Uhler66d874d2015-01-15 09:37:19 -08001055// Turn an absolute path into a path relative to the current working
1056// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -08001057static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001058 char buf[MAXPATHLEN];
1059 std::string cwd = getcwd(buf, MAXPATHLEN);
1060
1061 // Split the target and cwd paths into components.
1062 std::vector<std::string> target_path;
1063 std::vector<std::string> cwd_path;
1064 Split(target, '/', &target_path);
1065 Split(cwd, '/', &cwd_path);
1066
1067 // Reverse the path components, so we can use pop_back().
1068 std::reverse(target_path.begin(), target_path.end());
1069 std::reverse(cwd_path.begin(), cwd_path.end());
1070
1071 // Drop the common prefix of the paths. Because we reversed the path
1072 // components, this becomes the common suffix of target_path and cwd_path.
1073 while (!target_path.empty() && !cwd_path.empty()
1074 && target_path.back() == cwd_path.back()) {
1075 target_path.pop_back();
1076 cwd_path.pop_back();
1077 }
1078
1079 // For each element of the remaining cwd_path, add '..' to the beginning
1080 // of the target path. Because we reversed the path components, we add to
1081 // the end of target_path.
1082 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1083 target_path.push_back("..");
1084 }
1085
1086 // Reverse again to get the right path order, and join to get the result.
1087 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001088 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001089}
1090
1091// Case: Non-absolute path to Dex location.
1092// Expect: Not sure, but it shouldn't crash.
1093TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1094 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1095 Copy(GetDexSrc1(), abs_dex_location);
1096
1097 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -07001098 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001099
1100 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001101 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001102 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001103 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1104 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001105}
1106
1107// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001108// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001109TEST_F(OatFileAssistantTest, ShortDexLocation) {
1110 std::string dex_location = "/xx";
1111
Richard Uhlerd1472a22016-04-15 15:18:56 -07001112 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001113
1114 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001115 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1116 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001117 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1118 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001119 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001120}
1121
1122// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001123// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001124TEST_F(OatFileAssistantTest, LongDexExtension) {
1125 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1126 Copy(GetDexSrc1(), dex_location);
1127
Richard Uhlerd1472a22016-04-15 15:18:56 -07001128 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001129
Richard Uhler7225a8d2016-11-22 10:12:03 +00001130 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001131 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001132
1133 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001134 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1135 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001136}
1137
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001138
Richard Uhler66d874d2015-01-15 09:37:19 -08001139// A task to generate a dex location. Used by the RaceToGenerate test.
1140class RaceGenerateTask : public Task {
1141 public:
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001142 RaceGenerateTask(const std::string& dex_location,
1143 const std::string& oat_location,
1144 Mutex* lock)
1145 : dex_location_(dex_location),
1146 oat_location_(oat_location),
1147 lock_(lock),
1148 loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001149 {}
1150
Andreas Gampefa6a1b02018-09-07 08:11:55 -07001151 void Run(Thread* self ATTRIBUTE_UNUSED) override {
Richard Uhler66d874d2015-01-15 09:37:19 -08001152 // Load the dex files, and save a pointer to the loaded oat file, so that
1153 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001154 std::vector<std::unique_ptr<const DexFile>> dex_files;
1155 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001156 const OatFile* oat_file = nullptr;
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001157 {
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001158 MutexLock mu(Thread::Current(), *lock_);
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001159 // Create the oat file.
1160 std::vector<std::string> args;
1161 args.push_back("--dex-file=" + dex_location_);
1162 args.push_back("--oat-file=" + oat_location_);
1163 std::string error_msg;
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001164 ASSERT_TRUE(DexoptTest::Dex2Oat(args, &error_msg)) << error_msg;
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001165 }
1166
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001167 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1168 dex_location_.c_str(),
Jeff Hao0cb17282017-07-12 14:51:49 -07001169 Runtime::Current()->GetSystemClassLoader(),
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001170 /*dex_elements=*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001171 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001172 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001173 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001174 if (dex_files[0]->GetOatDexFile() != nullptr) {
1175 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
1176 }
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001177 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001178 }
1179
1180 const OatFile* GetLoadedOatFile() const {
1181 return loaded_oat_file_;
1182 }
1183
1184 private:
1185 std::string dex_location_;
1186 std::string oat_location_;
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001187 Mutex* lock_;
Richard Uhler66d874d2015-01-15 09:37:19 -08001188 const OatFile* loaded_oat_file_;
1189};
1190
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001191// Test the case where dex2oat invocations race with multiple processes trying to
1192// load the oat file.
Richard Uhler66d874d2015-01-15 09:37:19 -08001193TEST_F(OatFileAssistantTest, RaceToGenerate) {
1194 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001195 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001196
Jeff Hao0cb17282017-07-12 14:51:49 -07001197 // Start the runtime to initialize the system's class loader.
1198 Thread::Current()->TransitionFromSuspendedToRunnable();
1199 runtime_->Start();
1200
Richard Uhler66d874d2015-01-15 09:37:19 -08001201 // We use the lib core dex file, because it's large, and hopefully should
1202 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001203 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001204
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001205 const size_t kNumThreads = 32;
Richard Uhler66d874d2015-01-15 09:37:19 -08001206 Thread* self = Thread::Current();
1207 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1208 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001209 Mutex lock("RaceToGenerate");
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001210 for (size_t i = 0; i < kNumThreads; i++) {
Nicolas Geoffray1e76d7a2018-09-03 13:23:34 +01001211 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location, &lock));
Richard Uhler66d874d2015-01-15 09:37:19 -08001212 thread_pool.AddTask(self, task.get());
1213 tasks.push_back(std::move(task));
1214 }
1215 thread_pool.StartWorkers(self);
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001216 thread_pool.Wait(self, /* do_work= */ true, /* may_hold_locks= */ false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001217
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001218 // Verify that tasks which got an oat file got a unique one.
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001219 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001220 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001221 const OatFile* oat_file = task->GetLoadedOatFile();
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001222 if (oat_file != nullptr) {
1223 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1224 oat_files.insert(oat_file);
1225 }
Richard Uhler66d874d2015-01-15 09:37:19 -08001226 }
1227}
1228
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001229// Case: We have a DEX file and an ODEX file, and no OAT file,
Vladimir Markoe0669322018-09-03 15:44:54 +01001230// Expect: We should load the odex file executable.
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001231TEST_F(DexoptTest, LoadDexOdexNoOat) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001232 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001233 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001234
1235 // Create the dex and odex files
1236 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001237 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001238
1239 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001240 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001241
1242 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1243 ASSERT_TRUE(oat_file.get() != nullptr);
Vladimir Markoe0669322018-09-03 15:44:54 +01001244 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -08001245 std::vector<std::unique_ptr<const DexFile>> dex_files;
1246 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1247 EXPECT_EQ(1u, dex_files.size());
1248}
1249
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001250// Case: We have a MultiDEX file and an ODEX file, and no OAT file.
Vladimir Markoe0669322018-09-03 15:44:54 +01001251// Expect: We should load the odex file executable.
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001252TEST_F(DexoptTest, LoadMultiDexOdexNoOat) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001253 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001254 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001255
1256 // Create the dex and odex files
1257 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001258 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001259
1260 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001261 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001262
1263 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1264 ASSERT_TRUE(oat_file.get() != nullptr);
Vladimir Markoe0669322018-09-03 15:44:54 +01001265 EXPECT_TRUE(oat_file->IsExecutable());
Richard Uhler66d874d2015-01-15 09:37:19 -08001266 std::vector<std::unique_ptr<const DexFile>> dex_files;
1267 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1268 EXPECT_EQ(2u, dex_files.size());
1269}
1270
Richard Uhlerb81881d2016-04-19 13:08:04 -07001271TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001272 std::string error_msg;
1273 std::string odex_file;
1274
Richard Uhlerb81881d2016-04-19 13:08:04 -07001275 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001276 "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001277 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001278
Richard Uhlerb81881d2016-04-19 13:08:04 -07001279 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001280 "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001281 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001282
Richard Uhlerb81881d2016-04-19 13:08:04 -07001283 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001284 "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001285 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001286 "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001287}
1288
Richard Uhler23cedd22015-04-08 13:17:29 -07001289// Verify the dexopt status values from dalvik.system.DexFile
1290// match the OatFileAssistant::DexOptStatus values.
1291TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001292 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1293 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1294 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1295 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1296 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001297 };
1298
Richard Uhler23cedd22015-04-08 13:17:29 -07001299 ScopedObjectAccess soa(Thread::Current());
1300 StackHandleScope<1> hs(soa.Self());
1301 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1302 Handle<mirror::Class> dexfile(
1303 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
Andreas Gampefa4333d2017-02-14 11:10:34 -08001304 ASSERT_FALSE(dexfile == nullptr);
Richard Uhler23cedd22015-04-08 13:17:29 -07001305 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1306
Richard Uhler7225a8d2016-11-22 10:12:03 +00001307 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1308 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001309 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001310 ASSERT_FALSE(art_field == nullptr);
1311 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1312 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1313 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001314}
Richard Uhler66d874d2015-01-15 09:37:19 -08001315
Calin Juravle44e5efa2017-09-12 00:54:26 -07001316TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
1317 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1318 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1319 Copy(GetDexSrc1(), dex_location);
1320 Copy(GetDexSrc2(), context_location);
1321
1322 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1323
Calin Juravle44e5efa2017-09-12 00:54:26 -07001324 std::string error_msg;
1325 std::string context_str = "PCL[" + context_location + "]";
1326 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1327 ASSERT_TRUE(context != nullptr);
1328 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1329
Calin Juravle44e5efa2017-09-12 00:54:26 -07001330 // Update the context by overriding the jar file.
1331 Copy(GetMultiDexSrc2(), context_location);
1332 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1333 ASSERT_TRUE(updated_context != nullptr);
1334 // DexOptNeeded should advise compilation from scratch.
1335 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
1336 oat_file_assistant.GetDexOptNeeded(
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001337 CompilerFilter::kDefaultCompilerFilter,
Andreas Gampe98ea9d92018-10-19 14:06:15 -07001338 /* profile_changed= */ false,
1339 /* downgrade= */ false,
Nicolas Geoffray3d8a78a2018-08-29 21:10:16 +00001340 updated_context.get()));
Nicolas Geoffray29742602017-12-14 10:09:03 +00001341}
1342
Richard Uhler66d874d2015-01-15 09:37:19 -08001343// TODO: More Tests:
1344// * Test class linker falls back to unquickened dex for DexNoOat
1345// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001346// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001347// * Test for status of oat while oat is being generated (how?)
1348// * Test case where 32 and 64 bit boot class paths differ,
1349// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1350// 64 bit boot class paths.
1351// * Test unexpected scenarios (?):
1352// - Dex is stripped, don't have odex.
1353// - Oat file corrupted after status check, before reload unexecutable
1354// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001355} // namespace art