blob: 65481fc58a5b86c6c6f5fe5af33d4921b84e71bc [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 Sehr8f4b0562018-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 Brazdil4fe044c2018-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
Igor Murashkin2ffb7032017-11-08 13:35:21 -080044static const std::string kSpecialSharedLibrary = "&"; // NOLINT [runtime/string] [4]
Calin Juravle44e5efa2017-09-12 00:54:26 -070045static ClassLoaderContext* kSpecialSharedLibraryContext = nullptr;
Calin Juravle27e0d1f2017-07-26 00:16:07 -070046
David Brazdil4fe044c2018-05-14 15:24:34 +010047static constexpr char kDex2oatCmdLineHiddenApiArg[] = " --runtime-arg -Xhidden-api-checks";
48
Calin Juravle5f9a8012018-02-12 20:27:46 -080049class OatFileAssistantTest : public DexoptTest {
50 public:
51 void VerifyOptimizationStatus(const std::string& file,
52 const std::string& expected_filter,
53 const std::string& expected_reason) {
54 std::string compilation_filter;
55 std::string compilation_reason;
56 OatFileAssistant::GetOptimizationStatus(
57 file, kRuntimeISA, &compilation_filter, &compilation_reason);
58
59 ASSERT_EQ(expected_filter, compilation_filter);
60 ASSERT_EQ(expected_reason, compilation_reason);
61 }
62
63 void VerifyOptimizationStatus(const std::string& file,
64 CompilerFilter::Filter expected_filter,
65 const std::string& expected_reason) {
66 VerifyOptimizationStatus(
67 file, CompilerFilter::NameOfFilter(expected_filter), expected_reason);
68 }
69};
Richard Uhler66d874d2015-01-15 09:37:19 -080070
Calin Juravle36eb3132017-01-13 16:32:38 -080071class OatFileAssistantNoDex2OatTest : public DexoptTest {
Richard Uhler66d874d2015-01-15 09:37:19 -080072 public:
73 virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
Calin Juravle36eb3132017-01-13 16:32:38 -080074 DexoptTest::SetUpRuntimeOptions(options);
Richard Uhler66d874d2015-01-15 09:37:19 -080075 options->push_back(std::make_pair("-Xnodex2oat", nullptr));
76 }
77};
78
Calin Juravle357c66d2017-05-04 01:57:17 +000079class ScopedNonWritable {
80 public:
81 explicit ScopedNonWritable(const std::string& dex_location) {
82 is_valid_ = false;
83 size_t pos = dex_location.rfind('/');
84 if (pos != std::string::npos) {
85 is_valid_ = true;
86 dex_parent_ = dex_location.substr(0, pos);
87 if (chmod(dex_parent_.c_str(), 0555) != 0) {
88 PLOG(ERROR) << "Could not change permissions on " << dex_parent_;
89 }
90 }
91 }
92
93 bool IsSuccessful() { return is_valid_ && (access(dex_parent_.c_str(), W_OK) != 0); }
94
95 ~ScopedNonWritable() {
96 if (is_valid_) {
97 if (chmod(dex_parent_.c_str(), 0777) != 0) {
98 PLOG(ERROR) << "Could not restore permissions on " << dex_parent_;
99 }
100 }
101 }
102
103 private:
104 std::string dex_parent_;
105 bool is_valid_;
106};
107
108static bool IsExecutedAsRoot() {
109 return geteuid() == 0;
110}
Calin Juravle36eb3132017-01-13 16:32:38 -0800111
Richard Uhler66d874d2015-01-15 09:37:19 -0800112// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700113// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800114TEST_F(OatFileAssistantTest, DexNoOat) {
115 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
116 Copy(GetDexSrc1(), dex_location);
117
Richard Uhlerd1472a22016-04-15 15:18:56 -0700118 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800119
Richard Uhler7225a8d2016-11-22 10:12:03 +0000120 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100121 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000122 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100123 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000124 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000125 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000126 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000127 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800128
129 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000130 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
131 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700132 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800133
134 VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
Richard Uhler66d874d2015-01-15 09:37:19 -0800135}
136
137// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700138// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800139TEST_F(OatFileAssistantTest, NoDexNoOat) {
140 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
141
Richard Uhlerd1472a22016-04-15 15:18:56 -0700142 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800143
Andreas Gampe29d38e72016-03-23 15:31:51 +0000144 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
145 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700146 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
147
148 // Trying to make the oat file up to date should not fail or crash.
149 std::string error_msg;
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700150 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -0700151 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700152
153 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800154 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
155 EXPECT_EQ(nullptr, oat_file.get());
156}
157
Calin Juravle357c66d2017-05-04 01:57:17 +0000158// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
159// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
160TEST_F(OatFileAssistantTest, OdexUpToDate) {
161 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
162 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
163 Copy(GetDexSrc1(), dex_location);
Calin Juravle5f9a8012018-02-12 20:27:46 -0800164 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000165
166 // For the use of oat location by making the dex parent not writable.
167 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
168
169 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
170 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
171 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
172 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
173 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
174 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
175 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
176 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
177
178 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
179 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
180 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
181 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800182
183 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000184}
185
186// Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
187// file via a symlink.
188// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
189TEST_F(OatFileAssistantTest, OdexUpToDateSymLink) {
190 std::string scratch_dir = GetScratchDir();
191 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
192 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
193
194 Copy(GetDexSrc1(), dex_location);
195 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
196
197 // Now replace the dex location with a symlink.
198 std::string link = scratch_dir + "/link";
199 ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str()));
200 dex_location = link + "/OdexUpToDate.jar";
201
202 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
203
204 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
205 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
206 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
207 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
208 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
209 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
210 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
211 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
212
213 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
214 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
215 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
216 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
217}
218
Richard Uhler66d874d2015-01-15 09:37:19 -0800219// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700220// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800221TEST_F(OatFileAssistantTest, OatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000222 if (IsExecutedAsRoot()) {
223 // We cannot simulate non writable locations when executed as root: b/38000545.
224 LOG(ERROR) << "Test skipped because it's running as root";
225 return;
226 }
227
Richard Uhler66d874d2015-01-15 09:37:19 -0800228 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
229 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000230 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800231
Calin Juravle357c66d2017-05-04 01:57:17 +0000232 // For the use of oat location by making the dex parent not writable.
233 ScopedNonWritable scoped_non_writable(dex_location);
234 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
235
236 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
237
238 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
239 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
240 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
241 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
242 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
243 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
244 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
245 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
246
247 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
248 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
249 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
250 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800251
252 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "unknown");
Calin Juravle357c66d2017-05-04 01:57:17 +0000253}
254
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700255// Case: Passing valid file descriptors of updated odex/vdex filesalong with
256// the dex file.
257// Expect: The status is kNoDexOptNeeded.
258TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) {
259 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
260 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
261 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
262
263 Copy(GetDexSrc1(), dex_location);
264 GenerateOatForTest(dex_location.c_str(),
265 odex_location.c_str(),
266 CompilerFilter::kSpeed,
267 true,
268 false,
269 false);
270
271 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY));
272 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700273 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700274
275 OatFileAssistant oat_file_assistant(dex_location.c_str(),
276 kRuntimeISA,
277 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000278 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700279 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700280 odex_fd.get(),
281 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700282 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
283 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
284 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
285 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
286 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
287 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
288 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
289 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
290
291 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
292 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
293 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
294 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
295}
296
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700297// Case: Passing invalid odex fd and valid vdex and zip fds.
298// Expect: The status should be kDex2OatForBootImage.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700299TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
300 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
301 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
302 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
303
304 Copy(GetDexSrc1(), dex_location);
305 GenerateOatForTest(dex_location.c_str(),
306 odex_location.c_str(),
307 CompilerFilter::kSpeed,
308 true,
309 false,
310 false);
311
312 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700313 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700314
315 OatFileAssistant oat_file_assistant(dex_location.c_str(),
316 kRuntimeISA,
317 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000318 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700319 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700320 -1 /* oat_fd */,
321 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700322 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
323 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700324 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
325 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
326
327 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700328 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
329 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700330 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700331}
332
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700333// Case: Passing invalid vdex fd and valid odex and zip fds.
334// Expect: The status should be kDex2OatFromScratch.
335TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
336 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
337 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
338
339 Copy(GetDexSrc1(), dex_location);
340 GenerateOatForTest(dex_location.c_str(),
341 odex_location.c_str(),
342 CompilerFilter::kSpeed,
343 true,
344 false,
345 false);
346
347 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY));
348 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
349
350 OatFileAssistant oat_file_assistant(dex_location.c_str(),
351 kRuntimeISA,
352 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000353 false,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700354 -1 /* vdex_fd */,
355 odex_fd.get(),
356 zip_fd.get());
357
358 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
359 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
360 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
361 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
362 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
363 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
364}
365
366// Case: Passing invalid vdex and odex fd with valid zip fd.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700367// Expect: The status is kDex2oatFromScratch.
368TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
369 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
370
371 Copy(GetDexSrc1(), dex_location);
372
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700373 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700374 OatFileAssistant oat_file_assistant(dex_location.c_str(),
375 kRuntimeISA,
376 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000377 false,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700378 -1 /* vdex_fd */,
379 -1 /* oat_fd */,
380 zip_fd);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700381 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
382 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
383 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
384 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
385}
386
Richard Uhler2f27abd2017-01-31 14:02:34 +0000387// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
388// ODEX file.
389TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000390 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000391 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000392
Richard Uhler9a37efc2016-08-05 16:32:55 -0700393 Copy(GetDexSrc1(), dex_location);
394
Richard Uhler2f27abd2017-01-31 14:02:34 +0000395 // Generating and deleting the oat file should have the side effect of
396 // creating an up-to-date vdex file.
Calin Juravle357c66d2017-05-04 01:57:17 +0000397 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
398 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000399
Calin Juravle357c66d2017-05-04 01:57:17 +0000400 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000401
402 // Even though the vdex file is up to date, because we don't have the oat
403 // file, we can't know that the vdex depends on the boot image and is up to
404 // date with respect to the boot image. Instead we must assume the vdex file
405 // depends on the boot image and is out of date with respect to the boot
406 // image.
407 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
408 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
409
410 // Make sure we don't crash in this case when we dump the status. We don't
411 // care what the actual dumped value is.
412 oat_file_assistant.GetStatusDump();
Calin Juravle5f9a8012018-02-12 20:27:46 -0800413
414 VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
Richard Uhler2f27abd2017-01-31 14:02:34 +0000415}
416
417// Case: We have a DEX file and empty VDEX and ODEX files.
418TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
419 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
420 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
421 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
422
423 Copy(GetDexSrc1(), dex_location);
Richard Uhler5cd59292017-02-01 12:54:23 +0000424 ScratchFile vdex_file(vdex_location.c_str());
425 ScratchFile odex_file(odex_location.c_str());
Richard Uhler2f27abd2017-01-31 14:02:34 +0000426
427 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
428 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
429 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
430}
431
432// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
433// file.
434TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000435 if (IsExecutedAsRoot()) {
436 // We cannot simulate non writable locations when executed as root: b/38000545.
437 LOG(ERROR) << "Test skipped because it's running as root";
438 return;
439 }
Richard Uhler2f27abd2017-01-31 14:02:34 +0000440
441 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
442 std::string oat_location;
443 std::string error_msg;
444 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
445 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
446
447 Copy(GetDexSrc1(), dex_location);
448 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
449 ASSERT_EQ(0, unlink(oat_location.c_str()));
450
Calin Juravle357c66d2017-05-04 01:57:17 +0000451 ScopedNonWritable scoped_non_writable(dex_location);
452 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700453 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
454
Richard Uhler2f27abd2017-01-31 14:02:34 +0000455 // Even though the vdex file is up to date, because we don't have the oat
456 // file, we can't know that the vdex depends on the boot image and is up to
457 // date with respect to the boot image. Instead we must assume the vdex file
458 // depends on the boot image and is out of date with respect to the boot
459 // image.
460 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700461 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700462}
463
Andreas Gampe29d38e72016-03-23 15:31:51 +0000464// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700465// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
466// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000467TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000468 if (IsExecutedAsRoot()) {
469 // We cannot simulate non writable locations when executed as root: b/38000545.
470 LOG(ERROR) << "Test skipped because it's running as root";
471 return;
472 }
473
Andreas Gampe29d38e72016-03-23 15:31:51 +0000474 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
475 Copy(GetDexSrc1(), dex_location);
476 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
477
Calin Juravle357c66d2017-05-04 01:57:17 +0000478 ScopedNonWritable scoped_non_writable(dex_location);
479 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
480
Richard Uhlerd1472a22016-04-15 15:18:56 -0700481 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000482
483 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700484 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000485 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100486 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000487 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700488 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000489 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100490 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000491
492 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000493 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000494 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
495 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
496}
497
Richard Uhler66d874d2015-01-15 09:37:19 -0800498// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700499// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800500TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
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 }
506
Richard Uhler66d874d2015-01-15 09:37:19 -0800507 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
508 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000509 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800510
Calin Juravle357c66d2017-05-04 01:57:17 +0000511 ScopedNonWritable scoped_non_writable(dex_location);
512 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
513
Richard Uhlerd1472a22016-04-15 15:18:56 -0700514 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000515 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700516 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700517 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700518
519 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700520 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800521 ASSERT_TRUE(oat_file.get() != nullptr);
522 EXPECT_TRUE(oat_file->IsExecutable());
523 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700524 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
525 EXPECT_EQ(2u, dex_files.size());
526}
527
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000528// Case: We have a MultiDEX file where the non-main multdex entry is out of date.
Richard Uhler67ff7d12015-05-14 13:21:13 -0700529// Expect: The status is kDex2OatNeeded.
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000530TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000531 if (IsExecutedAsRoot()) {
532 // We cannot simulate non writable locations when executed as root: b/38000545.
533 LOG(ERROR) << "Test skipped because it's running as root";
534 return;
535 }
536
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000537 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
Richard Uhler67ff7d12015-05-14 13:21:13 -0700538
539 // Compile code for GetMultiDexSrc1.
540 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000541 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700542
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000543 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
Richard Uhler67ff7d12015-05-14 13:21:13 -0700544 // is out of date.
545 Copy(GetMultiDexSrc2(), dex_location);
546
Calin Juravle357c66d2017-05-04 01:57:17 +0000547 ScopedNonWritable scoped_non_writable(dex_location);
548 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
549
Richard Uhlerd1472a22016-04-15 15:18:56 -0700550 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000551 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700552 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700553 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700554}
555
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000556// Case: We have a stripped MultiDEX file where the non-main multidex entry is
557// out of date with respect to the odex file.
558TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
559 std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
560 std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
561
562 // Compile the oat from GetMultiDexSrc1.
563 Copy(GetMultiDexSrc1(), dex_location);
564 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
565
566 // Compile the odex from GetMultiDexSrc2, which has a different non-main
567 // dex checksum.
568 Copy(GetMultiDexSrc2(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100569 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000570
571 // Strip the dex file.
572 Copy(GetStrippedDexSrc1(), dex_location);
573
574 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable*/false);
575
576 // Because the dex file is stripped, the odex file is considered the source
577 // of truth for the dex checksums. The oat file should be considered
578 // unusable.
579 std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
580 ASSERT_TRUE(best_file.get() != nullptr);
581 EXPECT_EQ(best_file->GetLocation(), odex_location);
582 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
583 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
584 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
585}
586
Calin Juravle357c66d2017-05-04 01:57:17 +0000587// Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
Richard Uhlere5fed032015-03-18 08:21:11 -0700588// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700589// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700590TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
591 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000592 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
Richard Uhlere5fed032015-03-18 08:21:11 -0700593
594 // Create the dex file
595 Copy(GetMultiDexSrc1(), dex_location);
596
597 // Create the oat file with relative encoded dex location.
598 std::vector<std::string> args;
599 args.push_back("--dex-file=" + dex_location);
600 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
Calin Juravle357c66d2017-05-04 01:57:17 +0000601 args.push_back("--oat-file=" + odex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000602 args.push_back("--compiler-filter=speed");
Richard Uhlere5fed032015-03-18 08:21:11 -0700603
604 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700605 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700606
607 // Verify we can load both dex files.
Calin Juravle357c66d2017-05-04 01:57:17 +0000608 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
609
Richard Uhlere5fed032015-03-18 08:21:11 -0700610 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
611 ASSERT_TRUE(oat_file.get() != nullptr);
612 EXPECT_TRUE(oat_file->IsExecutable());
613 std::vector<std::unique_ptr<const DexFile>> dex_files;
614 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800615 EXPECT_EQ(2u, dex_files.size());
616}
617
Richard Uhler03bc6592016-11-22 09:42:04 +0000618// Case: We have a DEX file and an OAT file out of date with respect to the
619// dex checksum.
620TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000621 if (IsExecutedAsRoot()) {
622 // We cannot simulate non writable locations when executed as root: b/38000545.
623 LOG(ERROR) << "Test skipped because it's running as root";
624 return;
625 }
626
Richard Uhler03bc6592016-11-22 09:42:04 +0000627 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800628
629 // We create a dex, generate an oat for it, then overwrite the dex with a
630 // different dex to make the oat out of date.
631 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000632 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800633 Copy(GetDexSrc2(), dex_location);
634
Calin Juravle357c66d2017-05-04 01:57:17 +0000635 ScopedNonWritable scoped_non_writable(dex_location);
636 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
637
Richard Uhlerd1472a22016-04-15 15:18:56 -0700638 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000639 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100640 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000641 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000642 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800643
644 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000645 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
646 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
647 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
648}
649
Richard Uhler2f27abd2017-01-31 14:02:34 +0000650// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
651// to the dex checksum, but no ODEX file.
652TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000653 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000654 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000655
656 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000657 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
658 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000659 Copy(GetDexSrc2(), dex_location);
660
Calin Juravle357c66d2017-05-04 01:57:17 +0000661 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000662
663 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
664 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
665}
666
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000667// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
668// is out of date and there is no corresponding ODEX file.
669TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000670 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000671 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000672
673 Copy(GetMultiDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000674 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
675 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000676 Copy(GetMultiDexSrc2(), dex_location);
677
Calin Juravle357c66d2017-05-04 01:57:17 +0000678 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000679
680 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
681 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
682}
683
Richard Uhler03bc6592016-11-22 09:42:04 +0000684// Case: We have a DEX file and an OAT file out of date with respect to the
685// boot image.
686TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000687 if (IsExecutedAsRoot()) {
688 // We cannot simulate non writable locations when executed as root: b/38000545.
689 LOG(ERROR) << "Test skipped because it's running as root";
690 return;
691 }
692
Richard Uhler03bc6592016-11-22 09:42:04 +0000693 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
694
695 Copy(GetDexSrc1(), dex_location);
696 GenerateOatForTest(dex_location.c_str(),
697 CompilerFilter::kSpeed,
698 /*relocate*/true,
699 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000700 /*with_alternate_image*/true);
701
Calin Juravle357c66d2017-05-04 01:57:17 +0000702 ScopedNonWritable scoped_non_writable(dex_location);
703 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
704
Richard Uhler03bc6592016-11-22 09:42:04 +0000705 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000706 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100707 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000708 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100709 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000710 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000711 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
712
713 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
714 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
715 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
716 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
717}
718
719// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
720// respect to the boot image.
721// It shouldn't matter that the OAT file is out of date, because it is
722// verify-at-runtime.
723TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000724 if (IsExecutedAsRoot()) {
725 // We cannot simulate non writable locations when executed as root: b/38000545.
726 LOG(ERROR) << "Test skipped because it's running as root";
727 return;
728 }
729
Richard Uhler03bc6592016-11-22 09:42:04 +0000730 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
731
732 Copy(GetDexSrc1(), dex_location);
733 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100734 CompilerFilter::kExtract,
Richard Uhler03bc6592016-11-22 09:42:04 +0000735 /*relocate*/true,
736 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000737 /*with_alternate_image*/true);
738
Calin Juravle357c66d2017-05-04 01:57:17 +0000739 ScopedNonWritable scoped_non_writable(dex_location);
740 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
741
Richard Uhler03bc6592016-11-22 09:42:04 +0000742 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
743 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100744 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000745 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100746 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler03bc6592016-11-22 09:42:04 +0000747
748 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
749 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
750 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700751 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800752}
753
754// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800755TEST_F(OatFileAssistantTest, DexOdexNoOat) {
756 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700757 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800758
759 // Create the dex and odex files
760 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000761 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800762
763 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700764 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800765
Andreas Gampe29d38e72016-03-23 15:31:51 +0000766 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100767 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler5923b522016-12-08 09:48:01 +0000768 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000769 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800770
771 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000772 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
773 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700774 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700775
776 // We should still be able to get the non-executable odex file to run from.
777 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
778 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800779}
780
Richard Uhler5923b522016-12-08 09:48:01 +0000781// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800782TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
783 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700784 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800785
786 // Create the dex and odex files
787 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000788 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800789
790 // Strip the dex file
791 Copy(GetStrippedDexSrc1(), dex_location);
792
793 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700794 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800795
Richard Uhler5923b522016-12-08 09:48:01 +0000796 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000797 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800798
799 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000800 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000801 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700802 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800803
Richard Uhler66d874d2015-01-15 09:37:19 -0800804 // Verify we can load the dex files from it.
805 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
806 ASSERT_TRUE(oat_file.get() != nullptr);
807 EXPECT_TRUE(oat_file->IsExecutable());
808 std::vector<std::unique_ptr<const DexFile>> dex_files;
809 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
810 EXPECT_EQ(1u, dex_files.size());
811}
812
Richard Uhler5923b522016-12-08 09:48:01 +0000813// 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 -0800814TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
815 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700816 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800817
818 // Create the oat file from a different dex file so it looks out of date.
819 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000820 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800821
822 // Create the odex file
823 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000824 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800825
826 // Strip the dex file.
827 Copy(GetStrippedDexSrc1(), dex_location);
828
829 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700830 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800831
Andreas Gampe29d38e72016-03-23 15:31:51 +0000832 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100833 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000834 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
835 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Nicolas Geoffray08e9eed2017-04-25 17:36:51 +0100836 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, // Compiling from the .vdex file
Andreas Gampe29d38e72016-03-23 15:31:51 +0000837 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800838
839 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000840 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
841 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700842 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800843
844 // Verify we can load the dex files from it.
845 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
846 ASSERT_TRUE(oat_file.get() != nullptr);
847 EXPECT_TRUE(oat_file->IsExecutable());
848 std::vector<std::unique_ptr<const DexFile>> dex_files;
849 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
850 EXPECT_EQ(1u, dex_files.size());
851}
852
Richard Uhler9b994ea2015-06-24 08:44:19 -0700853// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
854// OAT file. Expect: The status is kNoDexOptNeeded.
855TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
856 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
857
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 Uhler9b994ea2015-06-24 08:44:19 -0700862
Andreas Gampe29d38e72016-03-23 15:31:51 +0000863 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
864 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
865 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100866 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000867 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100868 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700869
870 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000871 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
872 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700873 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
874
875 // Make the oat file up to date. This should have no effect.
876 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700877 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700878 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -0700879 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700880 error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700881
Andreas Gampe29d38e72016-03-23 15:31:51 +0000882 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
883 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700884
885 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000886 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
887 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700888 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
889}
890
Richard Uhler66d874d2015-01-15 09:37:19 -0800891// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
892// OAT files both have patch delta of 0.
Richard Uhler5923b522016-12-08 09:48:01 +0000893// Expect: It shouldn't crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800894TEST_F(OatFileAssistantTest, OdexOatOverlap) {
895 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700896 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800897
Calin Juravle357c66d2017-05-04 01:57:17 +0000898 // Create the dex, the odex and the oat files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800899 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000900 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle357c66d2017-05-04 01:57:17 +0000901 GenerateOatForTest(dex_location.c_str(),
902 CompilerFilter::kSpeed,
903 /*relocate*/false,
904 /*pic*/false,
905 /*with_alternate_image*/false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800906
907 // Verify things don't go bad.
Calin Juravle357c66d2017-05-04 01:57:17 +0000908 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800909
Calin Juravle357c66d2017-05-04 01:57:17 +0000910 // -kDex2OatForRelocation is expected rather than kDex2OatForRelocation
911 // based on the assumption that the odex location is more up-to-date than the oat
Richard Uhler70a84262016-11-08 16:51:51 +0000912 // location, even if they both need relocation.
Calin Juravle357c66d2017-05-04 01:57:17 +0000913 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000914 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800915
916 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000917 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
918 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700919 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800920
921 // Things aren't relocated, so it should fall back to interpreted.
922 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
923 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700924
Richard Uhler66d874d2015-01-15 09:37:19 -0800925 EXPECT_FALSE(oat_file->IsExecutable());
926 std::vector<std::unique_ptr<const DexFile>> dex_files;
927 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
928 EXPECT_EQ(1u, dex_files.size());
929}
930
Andreas Gampe29d38e72016-03-23 15:31:51 +0000931// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
932// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
933TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
934 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
935 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000936
937 // Create the dex and odex files
938 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100939 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000940
941 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700942 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000943
Andreas Gampe29d38e72016-03-23 15:31:51 +0000944 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100945 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000946 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000947 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000948
949 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000950 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000951 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000952 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
953}
954
Richard Uhler66d874d2015-01-15 09:37:19 -0800955// Case: We have a DEX file and up-to-date OAT file for it.
956// Expect: We should load an executable dex file.
957TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000958 if (IsExecutedAsRoot()) {
959 // We cannot simulate non writable locations when executed as root: b/38000545.
960 LOG(ERROR) << "Test skipped because it's running as root";
961 return;
962 }
963
Richard Uhler66d874d2015-01-15 09:37:19 -0800964 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
965
966 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000967 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800968
Calin Juravle357c66d2017-05-04 01:57:17 +0000969 ScopedNonWritable scoped_non_writable(dex_location);
970 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
971
Richard Uhler66d874d2015-01-15 09:37:19 -0800972 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700973 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000974
975 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
976 ASSERT_TRUE(oat_file.get() != nullptr);
977 EXPECT_TRUE(oat_file->IsExecutable());
978 std::vector<std::unique_ptr<const DexFile>> dex_files;
979 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
980 EXPECT_EQ(1u, dex_files.size());
981}
982
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100983// Case: We have a DEX file and up-to-date quicken OAT file for it.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000984// Expect: We should still load the oat file as executable.
985TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000986 if (IsExecutedAsRoot()) {
987 // We cannot simulate non writable locations when executed as root: b/38000545.
988 LOG(ERROR) << "Test skipped because it's running as root";
989 return;
990 }
991
Andreas Gampe29d38e72016-03-23 15:31:51 +0000992 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
993
994 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100995 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000996
Calin Juravle357c66d2017-05-04 01:57:17 +0000997 ScopedNonWritable scoped_non_writable(dex_location);
998 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
999
Andreas Gampe29d38e72016-03-23 15:31:51 +00001000 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001001 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001002
1003 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1004 ASSERT_TRUE(oat_file.get() != nullptr);
1005 EXPECT_TRUE(oat_file->IsExecutable());
1006 std::vector<std::unique_ptr<const DexFile>> dex_files;
1007 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1008 EXPECT_EQ(1u, dex_files.size());
1009}
1010
1011// Case: We have a DEX file and up-to-date OAT file for it.
1012// Expect: Loading non-executable should load the oat non-executable.
1013TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001014 if (IsExecutedAsRoot()) {
1015 // We cannot simulate non writable locations when executed as root: b/38000545.
1016 LOG(ERROR) << "Test skipped because it's running as root";
1017 return;
1018 }
1019
Richard Uhler66d874d2015-01-15 09:37:19 -08001020 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
1021
1022 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +00001023
1024 ScopedNonWritable scoped_non_writable(dex_location);
1025 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1026
Andreas Gampe29d38e72016-03-23 15:31:51 +00001027 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001028
1029 // 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, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001031
1032 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1033 ASSERT_TRUE(oat_file.get() != nullptr);
1034 EXPECT_FALSE(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
Richard Uhler8327cf72015-10-13 16:34:59 -07001040// Case: We don't have a DEX file and can't write the oat file.
1041// Expect: We should fail to generate the oat file without crashing.
1042TEST_F(OatFileAssistantTest, GenNoDex) {
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 }
Richard Uhler8327cf72015-10-13 16:34:59 -07001048
Calin Juravle357c66d2017-05-04 01:57:17 +00001049 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
1050
1051 ScopedNonWritable scoped_non_writable(dex_location);
1052 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1053
1054 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -07001055 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001056 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Calin Juravle357c66d2017-05-04 01:57:17 +00001057 // We should get kUpdateSucceeded from MakeUpToDate since there's nothing
1058 // that can be done in this situation.
1059 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001060 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Calin Juravle357c66d2017-05-04 01:57:17 +00001061
1062 // Verify it didn't create an oat in the default location (dalvik-cache).
1063 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
1064 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus());
1065 // Verify it didn't create the odex file in the default location (../oat/isa/...odex)
1066 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OdexFileStatus());
Richard Uhler8327cf72015-10-13 16:34:59 -07001067}
1068
Richard Uhler66d874d2015-01-15 09:37:19 -08001069// Turn an absolute path into a path relative to the current working
1070// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -08001071static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001072 char buf[MAXPATHLEN];
1073 std::string cwd = getcwd(buf, MAXPATHLEN);
1074
1075 // Split the target and cwd paths into components.
1076 std::vector<std::string> target_path;
1077 std::vector<std::string> cwd_path;
1078 Split(target, '/', &target_path);
1079 Split(cwd, '/', &cwd_path);
1080
1081 // Reverse the path components, so we can use pop_back().
1082 std::reverse(target_path.begin(), target_path.end());
1083 std::reverse(cwd_path.begin(), cwd_path.end());
1084
1085 // Drop the common prefix of the paths. Because we reversed the path
1086 // components, this becomes the common suffix of target_path and cwd_path.
1087 while (!target_path.empty() && !cwd_path.empty()
1088 && target_path.back() == cwd_path.back()) {
1089 target_path.pop_back();
1090 cwd_path.pop_back();
1091 }
1092
1093 // For each element of the remaining cwd_path, add '..' to the beginning
1094 // of the target path. Because we reversed the path components, we add to
1095 // the end of target_path.
1096 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1097 target_path.push_back("..");
1098 }
1099
1100 // Reverse again to get the right path order, and join to get the result.
1101 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001102 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001103}
1104
1105// Case: Non-absolute path to Dex location.
1106// Expect: Not sure, but it shouldn't crash.
1107TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1108 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1109 Copy(GetDexSrc1(), abs_dex_location);
1110
1111 std::string dex_location = MakePathRelative(abs_dex_location);
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());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001115 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001116 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 Uhler66d874d2015-01-15 09:37:19 -08001119}
1120
1121// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001122// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001123TEST_F(OatFileAssistantTest, ShortDexLocation) {
1124 std::string dex_location = "/xx";
1125
Richard Uhlerd1472a22016-04-15 15:18:56 -07001126 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001127
1128 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001129 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1130 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001131 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1132 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001133 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001134
Richard Uhler9b994ea2015-06-24 08:44:19 -07001135 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -08001136 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001137 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -07001138 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001139 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -07001140 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -08001141}
1142
1143// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001144// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001145TEST_F(OatFileAssistantTest, LongDexExtension) {
1146 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1147 Copy(GetDexSrc1(), dex_location);
1148
Richard Uhlerd1472a22016-04-15 15:18:56 -07001149 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001150
Richard Uhler7225a8d2016-11-22 10:12:03 +00001151 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001152 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001153
1154 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001155 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1156 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001157}
1158
1159// A task to generate a dex location. Used by the RaceToGenerate test.
1160class RaceGenerateTask : public Task {
1161 public:
1162 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
Jeff Haof0192c82016-03-28 20:39:50 -07001163 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001164 {}
1165
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01001166 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001167 // Load the dex files, and save a pointer to the loaded oat file, so that
1168 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001169 std::vector<std::unique_ptr<const DexFile>> dex_files;
1170 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001171 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001172 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1173 dex_location_.c_str(),
Jeff Hao0cb17282017-07-12 14:51:49 -07001174 Runtime::Current()->GetSystemClassLoader(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001175 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001176 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001177 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001178 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -07001179 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
1180 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001181 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001182 }
1183
1184 const OatFile* GetLoadedOatFile() const {
1185 return loaded_oat_file_;
1186 }
1187
1188 private:
1189 std::string dex_location_;
1190 std::string oat_location_;
1191 const OatFile* loaded_oat_file_;
1192};
1193
1194// Test the case where multiple processes race to generate an oat file.
1195// This simulates multiple processes using multiple threads.
1196//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001197// We want unique Oat files to be loaded even when there is a race to load.
1198// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1199// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001200TEST_F(OatFileAssistantTest, RaceToGenerate) {
1201 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001202 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001203
Jeff Hao0cb17282017-07-12 14:51:49 -07001204 // Start the runtime to initialize the system's class loader.
1205 Thread::Current()->TransitionFromSuspendedToRunnable();
1206 runtime_->Start();
1207
Richard Uhler66d874d2015-01-15 09:37:19 -08001208 // We use the lib core dex file, because it's large, and hopefully should
1209 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001210 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001211
1212 const int kNumThreads = 32;
1213 Thread* self = Thread::Current();
1214 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1215 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1216 for (int i = 0; i < kNumThreads; i++) {
1217 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1218 thread_pool.AddTask(self, task.get());
1219 tasks.push_back(std::move(task));
1220 }
1221 thread_pool.StartWorkers(self);
1222 thread_pool.Wait(self, true, false);
1223
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001224 // Verify every task got a unique oat file.
1225 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001226 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001227 const OatFile* oat_file = task->GetLoadedOatFile();
1228 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1229 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001230 }
1231}
1232
1233// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1234// disabled.
1235// Expect: We should load the odex file non-executable.
1236TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1237 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001238 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001239
1240 // Create the dex and odex files
1241 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001242 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001243
1244 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001245 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001246
1247 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1248 ASSERT_TRUE(oat_file.get() != nullptr);
1249 EXPECT_FALSE(oat_file->IsExecutable());
1250 std::vector<std::unique_ptr<const DexFile>> dex_files;
1251 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1252 EXPECT_EQ(1u, dex_files.size());
1253}
1254
1255// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1256// disabled.
1257// Expect: We should load the odex file non-executable.
1258TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1259 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001260 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001261
1262 // Create the dex and odex files
1263 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001264 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001265
1266 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001267 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001268
1269 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1270 ASSERT_TRUE(oat_file.get() != nullptr);
1271 EXPECT_FALSE(oat_file->IsExecutable());
1272 std::vector<std::unique_ptr<const DexFile>> dex_files;
1273 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1274 EXPECT_EQ(2u, dex_files.size());
1275}
1276
Richard Uhlerf4b34872016-04-13 11:03:46 -07001277TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
1278 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
1279 Copy(GetDexSrc1(), dex_location);
1280
Richard Uhlerd1472a22016-04-15 15:18:56 -07001281 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhlerf4b34872016-04-13 11:03:46 -07001282
1283 std::string error_msg;
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001284 Runtime::Current()->AddCompilerOption("--compiler-filter=quicken");
Richard Uhlerf4b34872016-04-13 11:03:46 -07001285 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001286 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001287 error_msg;
Calin Juravle357c66d2017-05-04 01:57:17 +00001288 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001289 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Calin Juravle357c66d2017-05-04 01:57:17 +00001290 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Richard Uhlerf4b34872016-04-13 11:03:46 -07001291 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1292
1293 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
1294 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001295 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg))
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001296 << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001297 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001298 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001299 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1300 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1301
1302 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
1303 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001304 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001305}
1306
Richard Uhlerb81881d2016-04-19 13:08:04 -07001307TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001308 std::string error_msg;
1309 std::string odex_file;
1310
Richard Uhlerb81881d2016-04-19 13:08:04 -07001311 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001312 "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001313 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001314
Richard Uhlerb81881d2016-04-19 13:08:04 -07001315 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001316 "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001317 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001318
Richard Uhlerb81881d2016-04-19 13:08:04 -07001319 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001320 "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001321 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001322 "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001323}
1324
Richard Uhler23cedd22015-04-08 13:17:29 -07001325// Verify the dexopt status values from dalvik.system.DexFile
1326// match the OatFileAssistant::DexOptStatus values.
1327TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001328 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1329 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1330 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1331 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1332 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
1333 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001334 };
1335
Richard Uhler23cedd22015-04-08 13:17:29 -07001336 ScopedObjectAccess soa(Thread::Current());
1337 StackHandleScope<1> hs(soa.Self());
1338 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1339 Handle<mirror::Class> dexfile(
1340 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
Andreas Gampefa4333d2017-02-14 11:10:34 -08001341 ASSERT_FALSE(dexfile == nullptr);
Richard Uhler23cedd22015-04-08 13:17:29 -07001342 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1343
Richard Uhler7225a8d2016-11-22 10:12:03 +00001344 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1345 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001346 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001347 ASSERT_FALSE(art_field == nullptr);
1348 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1349 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1350 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001351}
Richard Uhler66d874d2015-01-15 09:37:19 -08001352
Calin Juravle07c6d722017-06-07 17:06:12 +00001353// Verify that when no compiler filter is passed the default one from OatFileAssistant is used.
1354TEST_F(OatFileAssistantTest, DefaultMakeUpToDateFilter) {
1355 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1356 Copy(GetDexSrc1(), dex_location);
1357
1358 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1359
1360 const CompilerFilter::Filter default_filter =
1361 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1362 std::string error_msg;
1363 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001364 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001365 error_msg;
Calin Juravle07c6d722017-06-07 17:06:12 +00001366 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1367 oat_file_assistant.GetDexOptNeeded(default_filter));
1368 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1369 EXPECT_NE(nullptr, oat_file.get());
1370 EXPECT_EQ(default_filter, oat_file->GetCompilerFilter());
1371}
1372
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001373TEST_F(OatFileAssistantTest, MakeUpToDateWithSpecialSharedLibrary) {
1374 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1375 Copy(GetDexSrc1(), dex_location);
1376
1377 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1378
1379 const CompilerFilter::Filter default_filter =
1380 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1381 std::string error_msg;
Calin Juravle44e5efa2017-09-12 00:54:26 -07001382 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001383 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1384 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1385 oat_file_assistant.GetDexOptNeeded(default_filter));
1386 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1387 EXPECT_NE(nullptr, oat_file.get());
1388 EXPECT_EQ(kSpecialSharedLibrary,
1389 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1390}
1391
1392TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
1393 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1394 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1395 Copy(GetDexSrc1(), dex_location);
1396 Copy(GetDexSrc2(), context_location);
1397
1398 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1399
1400 const CompilerFilter::Filter default_filter =
1401 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1402 std::string error_msg;
1403 std::string context_str = "PCL[" + context_location + "]";
Calin Juravle44e5efa2017-09-12 00:54:26 -07001404 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1405 ASSERT_TRUE(context != nullptr);
1406 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1407
1408 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001409 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1410 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001411 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1412
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001413 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1414 EXPECT_NE(nullptr, oat_file.get());
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001415 EXPECT_EQ(context->EncodeContextForOatFile(""),
1416 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1417}
1418
David Brazdil4fe044c2018-05-14 15:24:34 +01001419TEST_F(OatFileAssistantTest, MakeUpToDateWithHiddenApiDisabled) {
1420 hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
1421 hiddenapi::EnforcementPolicy::kNoChecks);
1422
1423 std::string dex_location = GetScratchDir() + "/TestDexHiddenApiDisabled.jar";
1424 Copy(GetDexSrc1(), dex_location);
1425
1426 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1427 std::string error_msg;
1428 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1429 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1430
1431 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1432 EXPECT_NE(nullptr, oat_file.get());
1433
1434 const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
1435 EXPECT_NE(nullptr, cmd_line);
1436 EXPECT_EQ(nullptr, strstr(cmd_line, kDex2oatCmdLineHiddenApiArg));
1437}
1438
1439TEST_F(OatFileAssistantTest, MakeUpToDateWithHiddenApiEnabled) {
1440 hiddenapi::ScopedHiddenApiEnforcementPolicySetting hiddenapi_exemption(
1441 hiddenapi::EnforcementPolicy::kBlacklistOnly);
1442
1443 std::string dex_location = GetScratchDir() + "/TestDexHiddenApiEnabled.jar";
1444 Copy(GetDexSrc1(), dex_location);
1445
1446 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1447 std::string error_msg;
1448 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1449 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1450
1451 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1452 EXPECT_NE(nullptr, oat_file.get());
1453
1454 const char* cmd_line = oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kDex2OatCmdLineKey);
1455 EXPECT_NE(nullptr, cmd_line);
1456 EXPECT_NE(nullptr, strstr(cmd_line, kDex2oatCmdLineHiddenApiArg));
1457}
1458
Calin Juravle44e5efa2017-09-12 00:54:26 -07001459TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
1460 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1461 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1462 Copy(GetDexSrc1(), dex_location);
1463 Copy(GetDexSrc2(), context_location);
1464
1465 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1466
1467 const CompilerFilter::Filter default_filter =
1468 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1469 std::string error_msg;
1470 std::string context_str = "PCL[" + context_location + "]";
1471 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1472 ASSERT_TRUE(context != nullptr);
1473 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1474
1475 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1476 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1477 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1478 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1479
1480 // Update the context by overriding the jar file.
1481 Copy(GetMultiDexSrc2(), context_location);
1482 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1483 ASSERT_TRUE(updated_context != nullptr);
1484 // DexOptNeeded should advise compilation from scratch.
1485 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
1486 oat_file_assistant.GetDexOptNeeded(
1487 default_filter, false, false, updated_context.get()));
1488}
1489
Calin Juravle20c46442017-09-12 00:54:26 -07001490TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
1491 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1492 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1493 Copy(GetDexSrc1(), dex_location);
1494 Copy(GetDexSrc2(), context_location);
1495
1496 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1497
1498 const CompilerFilter::Filter default_filter =
1499 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1500 std::string error_msg;
1501 std::string context_str = "PCL[" + context_location + "]";
1502 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1503 ASSERT_TRUE(context != nullptr);
1504 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1505
1506 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1507 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1508
1509 // A relative context simulates a dependent split context.
1510 std::unique_ptr<ClassLoaderContext> relative_context =
1511 ClassLoaderContext::Create("PCL[ContextDex.jar]");
1512 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1513 oat_file_assistant.GetDexOptNeeded(
1514 default_filter, false, false, relative_context.get()));
1515}
1516
Nicolas Geoffray29742602017-12-14 10:09:03 +00001517TEST_F(OatFileAssistantTest, SystemOdex) {
1518 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
1519 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
1520 std::string system_location = GetAndroidRoot() + "/OatUpToDate.jar";
1521
1522 std::string error_msg;
1523
1524 Copy(GetDexSrc1(), dex_location);
1525 EXPECT_FALSE(LocationIsOnSystem(dex_location.c_str()));
1526
1527 {
1528 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1529 kRuntimeISA,
1530 true,
1531 false);
1532 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1533 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1534 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1535 }
1536
1537 {
1538 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1539 kRuntimeISA,
1540 true,
1541 true);
1542 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1543 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1544 EXPECT_FALSE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1545 }
1546
1547 Copy(GetDexSrc1(), system_location);
1548 EXPECT_TRUE(LocationIsOnSystem(system_location.c_str()));
1549
1550 {
1551 OatFileAssistant oat_file_assistant(system_location.c_str(),
1552 kRuntimeISA,
1553 true,
1554 false);
1555 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1556 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1557 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1558 }
1559
1560 {
1561 OatFileAssistant oat_file_assistant(system_location.c_str(),
1562 kRuntimeISA,
1563 true,
1564 true);
1565 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1566 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1567 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1568 }
1569}
1570
Richard Uhler66d874d2015-01-15 09:37:19 -08001571// TODO: More Tests:
1572// * Test class linker falls back to unquickened dex for DexNoOat
1573// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001574// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001575// * Test for status of oat while oat is being generated (how?)
1576// * Test case where 32 and 64 bit boot class paths differ,
1577// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1578// 64 bit boot class paths.
1579// * Test unexpected scenarios (?):
1580// - Dex is stripped, don't have odex.
1581// - Oat file corrupted after status check, before reload unexecutable
1582// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001583} // namespace art