blob: 72f7d028922318ca7448191e580ab9392c80aaf0 [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"
Vladimir Marko3481ba22015-04-13 12:22:36 +010030#include "class_linker-inl.h"
Calin Juravle27e0d1f2017-07-26 00:16:07 -070031#include "class_loader_context.h"
Jeff Hao0cb17282017-07-12 14:51:49 -070032#include "common_runtime_test.h"
Calin Juravle36eb3132017-01-13 16:32:38 -080033#include "dexopt_test.h"
Calin Juravle27e0d1f2017-07-26 00:16:07 -070034#include "oat_file.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070035#include "oat_file_manager.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080036#include "os.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070037#include "scoped_thread_state_change-inl.h"
Andreas Gampeb486a982017-06-01 13:45:54 -070038#include "thread-current-inl.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080039#include "utils.h"
40
41namespace art {
42
Igor Murashkin2ffb7032017-11-08 13:35:21 -080043static const std::string kSpecialSharedLibrary = "&"; // NOLINT [runtime/string] [4]
Calin Juravle44e5efa2017-09-12 00:54:26 -070044static ClassLoaderContext* kSpecialSharedLibraryContext = nullptr;
Calin Juravle27e0d1f2017-07-26 00:16:07 -070045
Calin Juravle5f9a8012018-02-12 20:27:46 -080046class OatFileAssistantTest : public DexoptTest {
47 public:
48 void VerifyOptimizationStatus(const std::string& file,
49 const std::string& expected_filter,
50 const std::string& expected_reason) {
51 std::string compilation_filter;
52 std::string compilation_reason;
53 OatFileAssistant::GetOptimizationStatus(
54 file, kRuntimeISA, &compilation_filter, &compilation_reason);
55
56 ASSERT_EQ(expected_filter, compilation_filter);
57 ASSERT_EQ(expected_reason, compilation_reason);
58 }
59
60 void VerifyOptimizationStatus(const std::string& file,
61 CompilerFilter::Filter expected_filter,
62 const std::string& expected_reason) {
63 VerifyOptimizationStatus(
64 file, CompilerFilter::NameOfFilter(expected_filter), expected_reason);
65 }
66};
Richard Uhler66d874d2015-01-15 09:37:19 -080067
Calin Juravle36eb3132017-01-13 16:32:38 -080068class OatFileAssistantNoDex2OatTest : public DexoptTest {
Richard Uhler66d874d2015-01-15 09:37:19 -080069 public:
70 virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
Calin Juravle36eb3132017-01-13 16:32:38 -080071 DexoptTest::SetUpRuntimeOptions(options);
Richard Uhler66d874d2015-01-15 09:37:19 -080072 options->push_back(std::make_pair("-Xnodex2oat", nullptr));
73 }
74};
75
Calin Juravle357c66d2017-05-04 01:57:17 +000076class ScopedNonWritable {
77 public:
78 explicit ScopedNonWritable(const std::string& dex_location) {
79 is_valid_ = false;
80 size_t pos = dex_location.rfind('/');
81 if (pos != std::string::npos) {
82 is_valid_ = true;
83 dex_parent_ = dex_location.substr(0, pos);
84 if (chmod(dex_parent_.c_str(), 0555) != 0) {
85 PLOG(ERROR) << "Could not change permissions on " << dex_parent_;
86 }
87 }
88 }
89
90 bool IsSuccessful() { return is_valid_ && (access(dex_parent_.c_str(), W_OK) != 0); }
91
92 ~ScopedNonWritable() {
93 if (is_valid_) {
94 if (chmod(dex_parent_.c_str(), 0777) != 0) {
95 PLOG(ERROR) << "Could not restore permissions on " << dex_parent_;
96 }
97 }
98 }
99
100 private:
101 std::string dex_parent_;
102 bool is_valid_;
103};
104
105static bool IsExecutedAsRoot() {
106 return geteuid() == 0;
107}
Calin Juravle36eb3132017-01-13 16:32:38 -0800108
Richard Uhler66d874d2015-01-15 09:37:19 -0800109// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700110// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800111TEST_F(OatFileAssistantTest, DexNoOat) {
112 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
113 Copy(GetDexSrc1(), dex_location);
114
Richard Uhlerd1472a22016-04-15 15:18:56 -0700115 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800116
Richard Uhler7225a8d2016-11-22 10:12:03 +0000117 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100118 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000119 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100120 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000121 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000122 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000123 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000124 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800125
126 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000127 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
128 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700129 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800130
131 VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
Richard Uhler66d874d2015-01-15 09:37:19 -0800132}
133
134// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700135// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800136TEST_F(OatFileAssistantTest, NoDexNoOat) {
137 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
138
Richard Uhlerd1472a22016-04-15 15:18:56 -0700139 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800140
Andreas Gampe29d38e72016-03-23 15:31:51 +0000141 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
142 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700143 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
144
145 // Trying to make the oat file up to date should not fail or crash.
146 std::string error_msg;
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700147 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -0700148 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700149
150 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800151 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
152 EXPECT_EQ(nullptr, oat_file.get());
153}
154
Calin Juravle357c66d2017-05-04 01:57:17 +0000155// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
156// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
157TEST_F(OatFileAssistantTest, OdexUpToDate) {
158 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
159 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
160 Copy(GetDexSrc1(), dex_location);
Calin Juravle5f9a8012018-02-12 20:27:46 -0800161 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000162
163 // For the use of oat location by making the dex parent not writable.
164 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
165
166 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
167 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
168 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
169 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
170 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
171 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
172 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
173 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
174
175 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
176 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
177 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
178 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800179
180 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "install");
Calin Juravle357c66d2017-05-04 01:57:17 +0000181}
182
183// Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
184// file via a symlink.
185// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
186TEST_F(OatFileAssistantTest, OdexUpToDateSymLink) {
187 std::string scratch_dir = GetScratchDir();
188 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
189 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
190
191 Copy(GetDexSrc1(), dex_location);
192 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
193
194 // Now replace the dex location with a symlink.
195 std::string link = scratch_dir + "/link";
196 ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str()));
197 dex_location = link + "/OdexUpToDate.jar";
198
199 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
200
201 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
202 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
203 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
204 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
205 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
206 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
207 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
208 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
209
210 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
211 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
212 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
213 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
214}
215
Richard Uhler66d874d2015-01-15 09:37:19 -0800216// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700217// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800218TEST_F(OatFileAssistantTest, OatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000219 if (IsExecutedAsRoot()) {
220 // We cannot simulate non writable locations when executed as root: b/38000545.
221 LOG(ERROR) << "Test skipped because it's running as root";
222 return;
223 }
224
Richard Uhler66d874d2015-01-15 09:37:19 -0800225 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
226 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000227 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800228
Calin Juravle357c66d2017-05-04 01:57:17 +0000229 // For the use of oat location by making the dex parent not writable.
230 ScopedNonWritable scoped_non_writable(dex_location);
231 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
232
233 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
234
235 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
236 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
237 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
238 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
239 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
240 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
241 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
242 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
243
244 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
245 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
246 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
247 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Calin Juravle5f9a8012018-02-12 20:27:46 -0800248
249 VerifyOptimizationStatus(dex_location, CompilerFilter::kSpeed, "unknown");
Calin Juravle357c66d2017-05-04 01:57:17 +0000250}
251
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700252// Case: Passing valid file descriptors of updated odex/vdex filesalong with
253// the dex file.
254// Expect: The status is kNoDexOptNeeded.
255TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) {
256 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
257 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
258 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
259
260 Copy(GetDexSrc1(), dex_location);
261 GenerateOatForTest(dex_location.c_str(),
262 odex_location.c_str(),
263 CompilerFilter::kSpeed,
264 true,
265 false,
266 false);
267
268 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY));
269 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700270 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700271
272 OatFileAssistant oat_file_assistant(dex_location.c_str(),
273 kRuntimeISA,
274 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000275 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700276 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700277 odex_fd.get(),
278 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700279 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
280 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
281 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
282 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
283 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
284 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
285 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
286 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
287
288 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
289 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
290 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
291 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
292}
293
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700294// Case: Passing invalid odex fd and valid vdex and zip fds.
295// Expect: The status should be kDex2OatForBootImage.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700296TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
297 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
298 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
299 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
300
301 Copy(GetDexSrc1(), dex_location);
302 GenerateOatForTest(dex_location.c_str(),
303 odex_location.c_str(),
304 CompilerFilter::kSpeed,
305 true,
306 false,
307 false);
308
309 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700310 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700311
312 OatFileAssistant oat_file_assistant(dex_location.c_str(),
313 kRuntimeISA,
314 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000315 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700316 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700317 -1 /* oat_fd */,
318 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700319 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
320 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700321 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
322 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
323
324 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700325 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
326 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700327 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700328}
329
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700330// Case: Passing invalid vdex fd and valid odex and zip fds.
331// Expect: The status should be kDex2OatFromScratch.
332TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
333 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
334 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
335
336 Copy(GetDexSrc1(), dex_location);
337 GenerateOatForTest(dex_location.c_str(),
338 odex_location.c_str(),
339 CompilerFilter::kSpeed,
340 true,
341 false,
342 false);
343
344 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY));
345 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
346
347 OatFileAssistant oat_file_assistant(dex_location.c_str(),
348 kRuntimeISA,
349 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000350 false,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700351 -1 /* vdex_fd */,
352 odex_fd.get(),
353 zip_fd.get());
354
355 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
356 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
357 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
358 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
359 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
360 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
361}
362
363// Case: Passing invalid vdex and odex fd with valid zip fd.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700364// Expect: The status is kDex2oatFromScratch.
365TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
366 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
367
368 Copy(GetDexSrc1(), dex_location);
369
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700370 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700371 OatFileAssistant oat_file_assistant(dex_location.c_str(),
372 kRuntimeISA,
373 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000374 false,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700375 -1 /* vdex_fd */,
376 -1 /* oat_fd */,
377 zip_fd);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700378 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
379 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
380 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
381 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
382}
383
Richard Uhler2f27abd2017-01-31 14:02:34 +0000384// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
385// ODEX file.
386TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000387 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000388 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000389
Richard Uhler9a37efc2016-08-05 16:32:55 -0700390 Copy(GetDexSrc1(), dex_location);
391
Richard Uhler2f27abd2017-01-31 14:02:34 +0000392 // Generating and deleting the oat file should have the side effect of
393 // creating an up-to-date vdex file.
Calin Juravle357c66d2017-05-04 01:57:17 +0000394 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
395 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000396
Calin Juravle357c66d2017-05-04 01:57:17 +0000397 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000398
399 // Even though the vdex file is up to date, because we don't have the oat
400 // file, we can't know that the vdex depends on the boot image and is up to
401 // date with respect to the boot image. Instead we must assume the vdex file
402 // depends on the boot image and is out of date with respect to the boot
403 // image.
404 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
405 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
406
407 // Make sure we don't crash in this case when we dump the status. We don't
408 // care what the actual dumped value is.
409 oat_file_assistant.GetStatusDump();
Calin Juravle5f9a8012018-02-12 20:27:46 -0800410
411 VerifyOptimizationStatus(dex_location, "run-from-apk", "unknown");
Richard Uhler2f27abd2017-01-31 14:02:34 +0000412}
413
414// Case: We have a DEX file and empty VDEX and ODEX files.
415TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
416 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
417 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
418 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
419
420 Copy(GetDexSrc1(), dex_location);
Richard Uhler5cd59292017-02-01 12:54:23 +0000421 ScratchFile vdex_file(vdex_location.c_str());
422 ScratchFile odex_file(odex_location.c_str());
Richard Uhler2f27abd2017-01-31 14:02:34 +0000423
424 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
425 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
426 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
427}
428
429// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
430// file.
431TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000432 if (IsExecutedAsRoot()) {
433 // We cannot simulate non writable locations when executed as root: b/38000545.
434 LOG(ERROR) << "Test skipped because it's running as root";
435 return;
436 }
Richard Uhler2f27abd2017-01-31 14:02:34 +0000437
438 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
439 std::string oat_location;
440 std::string error_msg;
441 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
442 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
443
444 Copy(GetDexSrc1(), dex_location);
445 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
446 ASSERT_EQ(0, unlink(oat_location.c_str()));
447
Calin Juravle357c66d2017-05-04 01:57:17 +0000448 ScopedNonWritable scoped_non_writable(dex_location);
449 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700450 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
451
Richard Uhler2f27abd2017-01-31 14:02:34 +0000452 // Even though the vdex file is up to date, because we don't have the oat
453 // file, we can't know that the vdex depends on the boot image and is up to
454 // date with respect to the boot image. Instead we must assume the vdex file
455 // depends on the boot image and is out of date with respect to the boot
456 // image.
457 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700458 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700459}
460
Andreas Gampe29d38e72016-03-23 15:31:51 +0000461// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700462// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
463// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000464TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000465 if (IsExecutedAsRoot()) {
466 // We cannot simulate non writable locations when executed as root: b/38000545.
467 LOG(ERROR) << "Test skipped because it's running as root";
468 return;
469 }
470
Andreas Gampe29d38e72016-03-23 15:31:51 +0000471 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
472 Copy(GetDexSrc1(), dex_location);
473 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
474
Calin Juravle357c66d2017-05-04 01:57:17 +0000475 ScopedNonWritable scoped_non_writable(dex_location);
476 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
477
Richard Uhlerd1472a22016-04-15 15:18:56 -0700478 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000479
480 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700481 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000482 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100483 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000484 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700485 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000486 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100487 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000488
489 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000490 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000491 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
492 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
493}
494
Richard Uhler66d874d2015-01-15 09:37:19 -0800495// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700496// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800497TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000498 if (IsExecutedAsRoot()) {
499 // We cannot simulate non writable locations when executed as root: b/38000545.
500 LOG(ERROR) << "Test skipped because it's running as root";
501 return;
502 }
503
Richard Uhler66d874d2015-01-15 09:37:19 -0800504 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
505 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000506 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800507
Calin Juravle357c66d2017-05-04 01:57:17 +0000508 ScopedNonWritable scoped_non_writable(dex_location);
509 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
510
Richard Uhlerd1472a22016-04-15 15:18:56 -0700511 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000512 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700513 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700514 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700515
516 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700517 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800518 ASSERT_TRUE(oat_file.get() != nullptr);
519 EXPECT_TRUE(oat_file->IsExecutable());
520 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700521 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
522 EXPECT_EQ(2u, dex_files.size());
523}
524
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000525// Case: We have a MultiDEX file where the non-main multdex entry is out of date.
Richard Uhler67ff7d12015-05-14 13:21:13 -0700526// Expect: The status is kDex2OatNeeded.
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000527TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000528 if (IsExecutedAsRoot()) {
529 // We cannot simulate non writable locations when executed as root: b/38000545.
530 LOG(ERROR) << "Test skipped because it's running as root";
531 return;
532 }
533
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000534 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
Richard Uhler67ff7d12015-05-14 13:21:13 -0700535
536 // Compile code for GetMultiDexSrc1.
537 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000538 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700539
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000540 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
Richard Uhler67ff7d12015-05-14 13:21:13 -0700541 // is out of date.
542 Copy(GetMultiDexSrc2(), dex_location);
543
Calin Juravle357c66d2017-05-04 01:57:17 +0000544 ScopedNonWritable scoped_non_writable(dex_location);
545 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
546
Richard Uhlerd1472a22016-04-15 15:18:56 -0700547 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000548 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700549 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700550 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700551}
552
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000553// Case: We have a stripped MultiDEX file where the non-main multidex entry is
554// out of date with respect to the odex file.
555TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
556 std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
557 std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
558
559 // Compile the oat from GetMultiDexSrc1.
560 Copy(GetMultiDexSrc1(), dex_location);
561 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
562
563 // Compile the odex from GetMultiDexSrc2, which has a different non-main
564 // dex checksum.
565 Copy(GetMultiDexSrc2(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100566 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000567
568 // Strip the dex file.
569 Copy(GetStrippedDexSrc1(), dex_location);
570
571 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable*/false);
572
573 // Because the dex file is stripped, the odex file is considered the source
574 // of truth for the dex checksums. The oat file should be considered
575 // unusable.
576 std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
577 ASSERT_TRUE(best_file.get() != nullptr);
578 EXPECT_EQ(best_file->GetLocation(), odex_location);
579 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
580 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
581 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
582}
583
Calin Juravle357c66d2017-05-04 01:57:17 +0000584// Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
Richard Uhlere5fed032015-03-18 08:21:11 -0700585// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700586// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700587TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
588 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000589 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
Richard Uhlere5fed032015-03-18 08:21:11 -0700590
591 // Create the dex file
592 Copy(GetMultiDexSrc1(), dex_location);
593
594 // Create the oat file with relative encoded dex location.
595 std::vector<std::string> args;
596 args.push_back("--dex-file=" + dex_location);
597 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
Calin Juravle357c66d2017-05-04 01:57:17 +0000598 args.push_back("--oat-file=" + odex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000599 args.push_back("--compiler-filter=speed");
Richard Uhlere5fed032015-03-18 08:21:11 -0700600
601 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700602 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700603
604 // Verify we can load both dex files.
Calin Juravle357c66d2017-05-04 01:57:17 +0000605 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
606
Richard Uhlere5fed032015-03-18 08:21:11 -0700607 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
608 ASSERT_TRUE(oat_file.get() != nullptr);
609 EXPECT_TRUE(oat_file->IsExecutable());
610 std::vector<std::unique_ptr<const DexFile>> dex_files;
611 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800612 EXPECT_EQ(2u, dex_files.size());
613}
614
Richard Uhler03bc6592016-11-22 09:42:04 +0000615// Case: We have a DEX file and an OAT file out of date with respect to the
616// dex checksum.
617TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000618 if (IsExecutedAsRoot()) {
619 // We cannot simulate non writable locations when executed as root: b/38000545.
620 LOG(ERROR) << "Test skipped because it's running as root";
621 return;
622 }
623
Richard Uhler03bc6592016-11-22 09:42:04 +0000624 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800625
626 // We create a dex, generate an oat for it, then overwrite the dex with a
627 // different dex to make the oat out of date.
628 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000629 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800630 Copy(GetDexSrc2(), dex_location);
631
Calin Juravle357c66d2017-05-04 01:57:17 +0000632 ScopedNonWritable scoped_non_writable(dex_location);
633 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
634
Richard Uhlerd1472a22016-04-15 15:18:56 -0700635 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000636 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100637 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000638 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000639 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800640
641 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000642 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
643 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
644 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
645}
646
Richard Uhler2f27abd2017-01-31 14:02:34 +0000647// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
648// to the dex checksum, but no ODEX file.
649TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000650 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000651 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000652
653 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000654 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
655 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000656 Copy(GetDexSrc2(), dex_location);
657
Calin Juravle357c66d2017-05-04 01:57:17 +0000658 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000659
660 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
661 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
662}
663
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000664// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
665// is out of date and there is no corresponding ODEX file.
666TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000667 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000668 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000669
670 Copy(GetMultiDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000671 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
672 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000673 Copy(GetMultiDexSrc2(), dex_location);
674
Calin Juravle357c66d2017-05-04 01:57:17 +0000675 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000676
677 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
678 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
679}
680
Richard Uhler03bc6592016-11-22 09:42:04 +0000681// Case: We have a DEX file and an OAT file out of date with respect to the
682// boot image.
683TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000684 if (IsExecutedAsRoot()) {
685 // We cannot simulate non writable locations when executed as root: b/38000545.
686 LOG(ERROR) << "Test skipped because it's running as root";
687 return;
688 }
689
Richard Uhler03bc6592016-11-22 09:42:04 +0000690 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
691
692 Copy(GetDexSrc1(), dex_location);
693 GenerateOatForTest(dex_location.c_str(),
694 CompilerFilter::kSpeed,
695 /*relocate*/true,
696 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000697 /*with_alternate_image*/true);
698
Calin Juravle357c66d2017-05-04 01:57:17 +0000699 ScopedNonWritable scoped_non_writable(dex_location);
700 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
701
Richard Uhler03bc6592016-11-22 09:42:04 +0000702 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000703 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100704 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000705 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100706 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000707 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000708 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
709
710 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
711 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
712 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
713 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
714}
715
716// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
717// respect to the boot image.
718// It shouldn't matter that the OAT file is out of date, because it is
719// verify-at-runtime.
720TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000721 if (IsExecutedAsRoot()) {
722 // We cannot simulate non writable locations when executed as root: b/38000545.
723 LOG(ERROR) << "Test skipped because it's running as root";
724 return;
725 }
726
Richard Uhler03bc6592016-11-22 09:42:04 +0000727 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
728
729 Copy(GetDexSrc1(), dex_location);
730 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100731 CompilerFilter::kExtract,
Richard Uhler03bc6592016-11-22 09:42:04 +0000732 /*relocate*/true,
733 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000734 /*with_alternate_image*/true);
735
Calin Juravle357c66d2017-05-04 01:57:17 +0000736 ScopedNonWritable scoped_non_writable(dex_location);
737 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
738
Richard Uhler03bc6592016-11-22 09:42:04 +0000739 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
740 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100741 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000742 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100743 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler03bc6592016-11-22 09:42:04 +0000744
745 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
746 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
747 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700748 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800749}
750
751// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800752TEST_F(OatFileAssistantTest, DexOdexNoOat) {
753 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700754 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800755
756 // Create the dex and odex files
757 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000758 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800759
760 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700761 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800762
Andreas Gampe29d38e72016-03-23 15:31:51 +0000763 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100764 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler5923b522016-12-08 09:48:01 +0000765 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000766 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800767
768 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000769 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
770 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700771 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700772
773 // We should still be able to get the non-executable odex file to run from.
774 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
775 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800776}
777
Richard Uhler5923b522016-12-08 09:48:01 +0000778// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800779TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
780 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700781 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800782
783 // Create the dex and odex files
784 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000785 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800786
787 // Strip the dex file
788 Copy(GetStrippedDexSrc1(), dex_location);
789
790 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700791 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800792
Richard Uhler5923b522016-12-08 09:48:01 +0000793 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000794 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800795
796 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000797 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000798 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700799 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800800
Richard Uhler66d874d2015-01-15 09:37:19 -0800801 // Verify we can load the dex files from it.
802 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
803 ASSERT_TRUE(oat_file.get() != nullptr);
804 EXPECT_TRUE(oat_file->IsExecutable());
805 std::vector<std::unique_ptr<const DexFile>> dex_files;
806 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
807 EXPECT_EQ(1u, dex_files.size());
808}
809
Richard Uhler5923b522016-12-08 09:48:01 +0000810// 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 -0800811TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
812 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700813 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800814
815 // Create the oat file from a different dex file so it looks out of date.
816 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000817 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800818
819 // Create the odex file
820 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000821 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800822
823 // Strip the dex file.
824 Copy(GetStrippedDexSrc1(), dex_location);
825
826 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700827 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800828
Andreas Gampe29d38e72016-03-23 15:31:51 +0000829 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100830 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000831 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
832 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Nicolas Geoffray08e9eed2017-04-25 17:36:51 +0100833 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, // Compiling from the .vdex file
Andreas Gampe29d38e72016-03-23 15:31:51 +0000834 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800835
836 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000837 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
838 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700839 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800840
841 // Verify we can load the dex files from it.
842 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
843 ASSERT_TRUE(oat_file.get() != nullptr);
844 EXPECT_TRUE(oat_file->IsExecutable());
845 std::vector<std::unique_ptr<const DexFile>> dex_files;
846 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
847 EXPECT_EQ(1u, dex_files.size());
848}
849
Richard Uhler9b994ea2015-06-24 08:44:19 -0700850// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
851// OAT file. Expect: The status is kNoDexOptNeeded.
852TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
853 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
854
855 Copy(GetStrippedDexSrc1(), dex_location);
856
857 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700858 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700859
Andreas Gampe29d38e72016-03-23 15:31:51 +0000860 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
861 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
862 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100863 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000864 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100865 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700866
867 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000868 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
869 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700870 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
871
872 // Make the oat file up to date. This should have no effect.
873 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700874 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700875 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -0700876 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700877 error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700878
Andreas Gampe29d38e72016-03-23 15:31:51 +0000879 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
880 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700881
882 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000883 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
884 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700885 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
886}
887
Richard Uhler66d874d2015-01-15 09:37:19 -0800888// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
889// OAT files both have patch delta of 0.
Richard Uhler5923b522016-12-08 09:48:01 +0000890// Expect: It shouldn't crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800891TEST_F(OatFileAssistantTest, OdexOatOverlap) {
892 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700893 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800894
Calin Juravle357c66d2017-05-04 01:57:17 +0000895 // Create the dex, the odex and the oat files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800896 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000897 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle357c66d2017-05-04 01:57:17 +0000898 GenerateOatForTest(dex_location.c_str(),
899 CompilerFilter::kSpeed,
900 /*relocate*/false,
901 /*pic*/false,
902 /*with_alternate_image*/false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800903
904 // Verify things don't go bad.
Calin Juravle357c66d2017-05-04 01:57:17 +0000905 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800906
Calin Juravle357c66d2017-05-04 01:57:17 +0000907 // -kDex2OatForRelocation is expected rather than kDex2OatForRelocation
908 // based on the assumption that the odex location is more up-to-date than the oat
Richard Uhler70a84262016-11-08 16:51:51 +0000909 // location, even if they both need relocation.
Calin Juravle357c66d2017-05-04 01:57:17 +0000910 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000911 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800912
913 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000914 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
915 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700916 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800917
918 // Things aren't relocated, so it should fall back to interpreted.
919 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
920 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700921
Richard Uhler66d874d2015-01-15 09:37:19 -0800922 EXPECT_FALSE(oat_file->IsExecutable());
923 std::vector<std::unique_ptr<const DexFile>> dex_files;
924 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
925 EXPECT_EQ(1u, dex_files.size());
926}
927
Andreas Gampe29d38e72016-03-23 15:31:51 +0000928// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
929// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
930TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
931 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
932 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000933
934 // Create the dex and odex files
935 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100936 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000937
938 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700939 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000940
Andreas Gampe29d38e72016-03-23 15:31:51 +0000941 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100942 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000943 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000944 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000945
946 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000947 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000948 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000949 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
950}
951
Richard Uhler66d874d2015-01-15 09:37:19 -0800952// Case: We have a DEX file and up-to-date OAT file for it.
953// Expect: We should load an executable dex file.
954TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000955 if (IsExecutedAsRoot()) {
956 // We cannot simulate non writable locations when executed as root: b/38000545.
957 LOG(ERROR) << "Test skipped because it's running as root";
958 return;
959 }
960
Richard Uhler66d874d2015-01-15 09:37:19 -0800961 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
962
963 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000964 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800965
Calin Juravle357c66d2017-05-04 01:57:17 +0000966 ScopedNonWritable scoped_non_writable(dex_location);
967 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
968
Richard Uhler66d874d2015-01-15 09:37:19 -0800969 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700970 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000971
972 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
973 ASSERT_TRUE(oat_file.get() != nullptr);
974 EXPECT_TRUE(oat_file->IsExecutable());
975 std::vector<std::unique_ptr<const DexFile>> dex_files;
976 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
977 EXPECT_EQ(1u, dex_files.size());
978}
979
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100980// Case: We have a DEX file and up-to-date quicken OAT file for it.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000981// Expect: We should still load the oat file as executable.
982TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000983 if (IsExecutedAsRoot()) {
984 // We cannot simulate non writable locations when executed as root: b/38000545.
985 LOG(ERROR) << "Test skipped because it's running as root";
986 return;
987 }
988
Andreas Gampe29d38e72016-03-23 15:31:51 +0000989 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
990
991 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100992 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000993
Calin Juravle357c66d2017-05-04 01:57:17 +0000994 ScopedNonWritable scoped_non_writable(dex_location);
995 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
996
Andreas Gampe29d38e72016-03-23 15:31:51 +0000997 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700998 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800999
1000 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1001 ASSERT_TRUE(oat_file.get() != nullptr);
1002 EXPECT_TRUE(oat_file->IsExecutable());
1003 std::vector<std::unique_ptr<const DexFile>> dex_files;
1004 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1005 EXPECT_EQ(1u, dex_files.size());
1006}
1007
1008// Case: We have a DEX file and up-to-date OAT file for it.
1009// Expect: Loading non-executable should load the oat non-executable.
1010TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001011 if (IsExecutedAsRoot()) {
1012 // We cannot simulate non writable locations when executed as root: b/38000545.
1013 LOG(ERROR) << "Test skipped because it's running as root";
1014 return;
1015 }
1016
Richard Uhler66d874d2015-01-15 09:37:19 -08001017 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
1018
1019 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +00001020
1021 ScopedNonWritable scoped_non_writable(dex_location);
1022 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1023
Andreas Gampe29d38e72016-03-23 15:31:51 +00001024 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001025
1026 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001027 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001028
1029 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1030 ASSERT_TRUE(oat_file.get() != nullptr);
1031 EXPECT_FALSE(oat_file->IsExecutable());
1032 std::vector<std::unique_ptr<const DexFile>> dex_files;
1033 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1034 EXPECT_EQ(1u, dex_files.size());
1035}
1036
Richard Uhler8327cf72015-10-13 16:34:59 -07001037// Case: We don't have a DEX file and can't write the oat file.
1038// Expect: We should fail to generate the oat file without crashing.
1039TEST_F(OatFileAssistantTest, GenNoDex) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001040 if (IsExecutedAsRoot()) {
1041 // We cannot simulate non writable locations when executed as root: b/38000545.
1042 LOG(ERROR) << "Test skipped because it's running as root";
1043 return;
1044 }
Richard Uhler8327cf72015-10-13 16:34:59 -07001045
Calin Juravle357c66d2017-05-04 01:57:17 +00001046 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
1047
1048 ScopedNonWritable scoped_non_writable(dex_location);
1049 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1050
1051 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -07001052 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001053 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Calin Juravle357c66d2017-05-04 01:57:17 +00001054 // We should get kUpdateSucceeded from MakeUpToDate since there's nothing
1055 // that can be done in this situation.
1056 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001057 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Calin Juravle357c66d2017-05-04 01:57:17 +00001058
1059 // Verify it didn't create an oat in the default location (dalvik-cache).
1060 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
1061 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus());
1062 // Verify it didn't create the odex file in the default location (../oat/isa/...odex)
1063 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OdexFileStatus());
Richard Uhler8327cf72015-10-13 16:34:59 -07001064}
1065
Richard Uhler66d874d2015-01-15 09:37:19 -08001066// Turn an absolute path into a path relative to the current working
1067// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -08001068static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001069 char buf[MAXPATHLEN];
1070 std::string cwd = getcwd(buf, MAXPATHLEN);
1071
1072 // Split the target and cwd paths into components.
1073 std::vector<std::string> target_path;
1074 std::vector<std::string> cwd_path;
1075 Split(target, '/', &target_path);
1076 Split(cwd, '/', &cwd_path);
1077
1078 // Reverse the path components, so we can use pop_back().
1079 std::reverse(target_path.begin(), target_path.end());
1080 std::reverse(cwd_path.begin(), cwd_path.end());
1081
1082 // Drop the common prefix of the paths. Because we reversed the path
1083 // components, this becomes the common suffix of target_path and cwd_path.
1084 while (!target_path.empty() && !cwd_path.empty()
1085 && target_path.back() == cwd_path.back()) {
1086 target_path.pop_back();
1087 cwd_path.pop_back();
1088 }
1089
1090 // For each element of the remaining cwd_path, add '..' to the beginning
1091 // of the target path. Because we reversed the path components, we add to
1092 // the end of target_path.
1093 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1094 target_path.push_back("..");
1095 }
1096
1097 // Reverse again to get the right path order, and join to get the result.
1098 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001099 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001100}
1101
1102// Case: Non-absolute path to Dex location.
1103// Expect: Not sure, but it shouldn't crash.
1104TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1105 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1106 Copy(GetDexSrc1(), abs_dex_location);
1107
1108 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -07001109 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001110
1111 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001112 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001113 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001114 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1115 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001116}
1117
1118// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001119// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001120TEST_F(OatFileAssistantTest, ShortDexLocation) {
1121 std::string dex_location = "/xx";
1122
Richard Uhlerd1472a22016-04-15 15:18:56 -07001123 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001124
1125 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001126 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1127 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001128 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1129 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001130 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001131
Richard Uhler9b994ea2015-06-24 08:44:19 -07001132 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -08001133 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001134 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -07001135 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001136 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -07001137 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -08001138}
1139
1140// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001141// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001142TEST_F(OatFileAssistantTest, LongDexExtension) {
1143 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1144 Copy(GetDexSrc1(), dex_location);
1145
Richard Uhlerd1472a22016-04-15 15:18:56 -07001146 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001147
Richard Uhler7225a8d2016-11-22 10:12:03 +00001148 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001149 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001150
1151 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001152 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1153 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001154}
1155
1156// A task to generate a dex location. Used by the RaceToGenerate test.
1157class RaceGenerateTask : public Task {
1158 public:
1159 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
Jeff Haof0192c82016-03-28 20:39:50 -07001160 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001161 {}
1162
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01001163 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001164 // Load the dex files, and save a pointer to the loaded oat file, so that
1165 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001166 std::vector<std::unique_ptr<const DexFile>> dex_files;
1167 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001168 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001169 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1170 dex_location_.c_str(),
Jeff Hao0cb17282017-07-12 14:51:49 -07001171 Runtime::Current()->GetSystemClassLoader(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001172 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001173 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001174 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001175 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -07001176 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
1177 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001178 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001179 }
1180
1181 const OatFile* GetLoadedOatFile() const {
1182 return loaded_oat_file_;
1183 }
1184
1185 private:
1186 std::string dex_location_;
1187 std::string oat_location_;
1188 const OatFile* loaded_oat_file_;
1189};
1190
1191// Test the case where multiple processes race to generate an oat file.
1192// This simulates multiple processes using multiple threads.
1193//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001194// We want unique Oat files to be loaded even when there is a race to load.
1195// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1196// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001197TEST_F(OatFileAssistantTest, RaceToGenerate) {
1198 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001199 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001200
Jeff Hao0cb17282017-07-12 14:51:49 -07001201 // Start the runtime to initialize the system's class loader.
1202 Thread::Current()->TransitionFromSuspendedToRunnable();
1203 runtime_->Start();
1204
Richard Uhler66d874d2015-01-15 09:37:19 -08001205 // We use the lib core dex file, because it's large, and hopefully should
1206 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001207 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001208
1209 const int kNumThreads = 32;
1210 Thread* self = Thread::Current();
1211 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1212 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1213 for (int i = 0; i < kNumThreads; i++) {
1214 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1215 thread_pool.AddTask(self, task.get());
1216 tasks.push_back(std::move(task));
1217 }
1218 thread_pool.StartWorkers(self);
1219 thread_pool.Wait(self, true, false);
1220
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001221 // Verify every task got a unique oat file.
1222 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001223 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001224 const OatFile* oat_file = task->GetLoadedOatFile();
1225 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1226 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001227 }
1228}
1229
1230// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1231// disabled.
1232// Expect: We should load the odex file non-executable.
1233TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1234 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001235 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001236
1237 // Create the dex and odex files
1238 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001239 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001240
1241 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001242 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001243
1244 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1245 ASSERT_TRUE(oat_file.get() != nullptr);
1246 EXPECT_FALSE(oat_file->IsExecutable());
1247 std::vector<std::unique_ptr<const DexFile>> dex_files;
1248 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1249 EXPECT_EQ(1u, dex_files.size());
1250}
1251
1252// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1253// disabled.
1254// Expect: We should load the odex file non-executable.
1255TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1256 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001257 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001258
1259 // Create the dex and odex files
1260 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001261 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001262
1263 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001264 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001265
1266 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1267 ASSERT_TRUE(oat_file.get() != nullptr);
1268 EXPECT_FALSE(oat_file->IsExecutable());
1269 std::vector<std::unique_ptr<const DexFile>> dex_files;
1270 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1271 EXPECT_EQ(2u, dex_files.size());
1272}
1273
Richard Uhlerf4b34872016-04-13 11:03:46 -07001274TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
1275 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
1276 Copy(GetDexSrc1(), dex_location);
1277
Richard Uhlerd1472a22016-04-15 15:18:56 -07001278 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhlerf4b34872016-04-13 11:03:46 -07001279
1280 std::string error_msg;
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001281 Runtime::Current()->AddCompilerOption("--compiler-filter=quicken");
Richard Uhlerf4b34872016-04-13 11:03:46 -07001282 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001283 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001284 error_msg;
Calin Juravle357c66d2017-05-04 01:57:17 +00001285 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001286 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Calin Juravle357c66d2017-05-04 01:57:17 +00001287 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Richard Uhlerf4b34872016-04-13 11:03:46 -07001288 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1289
1290 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
1291 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001292 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg))
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001293 << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001294 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001295 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001296 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1297 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1298
1299 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
1300 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001301 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001302}
1303
Richard Uhlerb81881d2016-04-19 13:08:04 -07001304TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001305 std::string error_msg;
1306 std::string odex_file;
1307
Richard Uhlerb81881d2016-04-19 13:08:04 -07001308 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001309 "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001310 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001311
Richard Uhlerb81881d2016-04-19 13:08:04 -07001312 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001313 "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001314 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001315
Richard Uhlerb81881d2016-04-19 13:08:04 -07001316 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001317 "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001318 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001319 "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001320}
1321
Richard Uhler23cedd22015-04-08 13:17:29 -07001322// Verify the dexopt status values from dalvik.system.DexFile
1323// match the OatFileAssistant::DexOptStatus values.
1324TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001325 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1326 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1327 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1328 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1329 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
1330 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001331 };
1332
Richard Uhler23cedd22015-04-08 13:17:29 -07001333 ScopedObjectAccess soa(Thread::Current());
1334 StackHandleScope<1> hs(soa.Self());
1335 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1336 Handle<mirror::Class> dexfile(
1337 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
Andreas Gampefa4333d2017-02-14 11:10:34 -08001338 ASSERT_FALSE(dexfile == nullptr);
Richard Uhler23cedd22015-04-08 13:17:29 -07001339 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1340
Richard Uhler7225a8d2016-11-22 10:12:03 +00001341 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1342 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001343 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001344 ASSERT_FALSE(art_field == nullptr);
1345 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1346 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1347 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001348}
Richard Uhler66d874d2015-01-15 09:37:19 -08001349
Calin Juravle07c6d722017-06-07 17:06:12 +00001350// Verify that when no compiler filter is passed the default one from OatFileAssistant is used.
1351TEST_F(OatFileAssistantTest, DefaultMakeUpToDateFilter) {
1352 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1353 Copy(GetDexSrc1(), dex_location);
1354
1355 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1356
1357 const CompilerFilter::Filter default_filter =
1358 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1359 std::string error_msg;
1360 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001361 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001362 error_msg;
Calin Juravle07c6d722017-06-07 17:06:12 +00001363 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1364 oat_file_assistant.GetDexOptNeeded(default_filter));
1365 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1366 EXPECT_NE(nullptr, oat_file.get());
1367 EXPECT_EQ(default_filter, oat_file->GetCompilerFilter());
1368}
1369
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001370TEST_F(OatFileAssistantTest, MakeUpToDateWithSpecialSharedLibrary) {
1371 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1372 Copy(GetDexSrc1(), dex_location);
1373
1374 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1375
1376 const CompilerFilter::Filter default_filter =
1377 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1378 std::string error_msg;
Calin Juravle44e5efa2017-09-12 00:54:26 -07001379 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001380 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1381 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1382 oat_file_assistant.GetDexOptNeeded(default_filter));
1383 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1384 EXPECT_NE(nullptr, oat_file.get());
1385 EXPECT_EQ(kSpecialSharedLibrary,
1386 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1387}
1388
1389TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
1390 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1391 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1392 Copy(GetDexSrc1(), dex_location);
1393 Copy(GetDexSrc2(), context_location);
1394
1395 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1396
1397 const CompilerFilter::Filter default_filter =
1398 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1399 std::string error_msg;
1400 std::string context_str = "PCL[" + context_location + "]";
Calin Juravle44e5efa2017-09-12 00:54:26 -07001401 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1402 ASSERT_TRUE(context != nullptr);
1403 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1404
1405 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001406 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1407 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001408 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1409
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001410 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1411 EXPECT_NE(nullptr, oat_file.get());
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001412 EXPECT_EQ(context->EncodeContextForOatFile(""),
1413 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1414}
1415
Calin Juravle44e5efa2017-09-12 00:54:26 -07001416TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
1417 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1418 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1419 Copy(GetDexSrc1(), dex_location);
1420 Copy(GetDexSrc2(), context_location);
1421
1422 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1423
1424 const CompilerFilter::Filter default_filter =
1425 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1426 std::string error_msg;
1427 std::string context_str = "PCL[" + context_location + "]";
1428 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1429 ASSERT_TRUE(context != nullptr);
1430 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1431
1432 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1433 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1434 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1435 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1436
1437 // Update the context by overriding the jar file.
1438 Copy(GetMultiDexSrc2(), context_location);
1439 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1440 ASSERT_TRUE(updated_context != nullptr);
1441 // DexOptNeeded should advise compilation from scratch.
1442 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
1443 oat_file_assistant.GetDexOptNeeded(
1444 default_filter, false, false, updated_context.get()));
1445}
1446
Calin Juravle20c46442017-09-12 00:54:26 -07001447TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
1448 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1449 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1450 Copy(GetDexSrc1(), dex_location);
1451 Copy(GetDexSrc2(), context_location);
1452
1453 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1454
1455 const CompilerFilter::Filter default_filter =
1456 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1457 std::string error_msg;
1458 std::string context_str = "PCL[" + context_location + "]";
1459 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1460 ASSERT_TRUE(context != nullptr);
1461 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1462
1463 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1464 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1465
1466 // A relative context simulates a dependent split context.
1467 std::unique_ptr<ClassLoaderContext> relative_context =
1468 ClassLoaderContext::Create("PCL[ContextDex.jar]");
1469 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1470 oat_file_assistant.GetDexOptNeeded(
1471 default_filter, false, false, relative_context.get()));
1472}
1473
Nicolas Geoffray29742602017-12-14 10:09:03 +00001474TEST_F(OatFileAssistantTest, SystemOdex) {
1475 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
1476 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
1477 std::string system_location = GetAndroidRoot() + "/OatUpToDate.jar";
1478
1479 std::string error_msg;
1480
1481 Copy(GetDexSrc1(), dex_location);
1482 EXPECT_FALSE(LocationIsOnSystem(dex_location.c_str()));
1483
1484 {
1485 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1486 kRuntimeISA,
1487 true,
1488 false);
1489 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1490 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1491 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1492 }
1493
1494 {
1495 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1496 kRuntimeISA,
1497 true,
1498 true);
1499 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1500 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1501 EXPECT_FALSE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1502 }
1503
1504 Copy(GetDexSrc1(), system_location);
1505 EXPECT_TRUE(LocationIsOnSystem(system_location.c_str()));
1506
1507 {
1508 OatFileAssistant oat_file_assistant(system_location.c_str(),
1509 kRuntimeISA,
1510 true,
1511 false);
1512 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1513 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1514 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1515 }
1516
1517 {
1518 OatFileAssistant oat_file_assistant(system_location.c_str(),
1519 kRuntimeISA,
1520 true,
1521 true);
1522 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1523 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1524 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1525 }
1526}
1527
Richard Uhler66d874d2015-01-15 09:37:19 -08001528// TODO: More Tests:
1529// * Test class linker falls back to unquickened dex for DexNoOat
1530// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001531// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001532// * Test for status of oat while oat is being generated (how?)
1533// * Test case where 32 and 64 bit boot class paths differ,
1534// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1535// 64 bit boot class paths.
1536// * Test unexpected scenarios (?):
1537// - Dex is stripped, don't have odex.
1538// - Oat file corrupted after status check, before reload unexecutable
1539// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001540} // namespace art