blob: 50f5e7a0d5fdc7da082de8d4a7f2ffc77be7f3af [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 Juravle36eb3132017-01-13 16:32:38 -080046class OatFileAssistantTest : public DexoptTest {};
Richard Uhler66d874d2015-01-15 09:37:19 -080047
Calin Juravle36eb3132017-01-13 16:32:38 -080048class OatFileAssistantNoDex2OatTest : public DexoptTest {
Richard Uhler66d874d2015-01-15 09:37:19 -080049 public:
50 virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
Calin Juravle36eb3132017-01-13 16:32:38 -080051 DexoptTest::SetUpRuntimeOptions(options);
Richard Uhler66d874d2015-01-15 09:37:19 -080052 options->push_back(std::make_pair("-Xnodex2oat", nullptr));
53 }
54};
55
Calin Juravle357c66d2017-05-04 01:57:17 +000056class ScopedNonWritable {
57 public:
58 explicit ScopedNonWritable(const std::string& dex_location) {
59 is_valid_ = false;
60 size_t pos = dex_location.rfind('/');
61 if (pos != std::string::npos) {
62 is_valid_ = true;
63 dex_parent_ = dex_location.substr(0, pos);
64 if (chmod(dex_parent_.c_str(), 0555) != 0) {
65 PLOG(ERROR) << "Could not change permissions on " << dex_parent_;
66 }
67 }
68 }
69
70 bool IsSuccessful() { return is_valid_ && (access(dex_parent_.c_str(), W_OK) != 0); }
71
72 ~ScopedNonWritable() {
73 if (is_valid_) {
74 if (chmod(dex_parent_.c_str(), 0777) != 0) {
75 PLOG(ERROR) << "Could not restore permissions on " << dex_parent_;
76 }
77 }
78 }
79
80 private:
81 std::string dex_parent_;
82 bool is_valid_;
83};
84
85static bool IsExecutedAsRoot() {
86 return geteuid() == 0;
87}
Calin Juravle36eb3132017-01-13 16:32:38 -080088
Richard Uhler66d874d2015-01-15 09:37:19 -080089// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -070090// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -080091TEST_F(OatFileAssistantTest, DexNoOat) {
92 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
93 Copy(GetDexSrc1(), dex_location);
94
Richard Uhlerd1472a22016-04-15 15:18:56 -070095 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -080096
Richard Uhler7225a8d2016-11-22 10:12:03 +000097 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +010098 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +000099 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100100 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000101 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000102 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000103 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000104 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800105
106 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000107 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
108 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700109 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800110}
111
112// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700113// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800114TEST_F(OatFileAssistantTest, NoDexNoOat) {
115 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
116
Richard Uhlerd1472a22016-04-15 15:18:56 -0700117 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800118
Andreas Gampe29d38e72016-03-23 15:31:51 +0000119 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
120 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700121 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
122
123 // Trying to make the oat file up to date should not fail or crash.
124 std::string error_msg;
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700125 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -0700126 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700127
128 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800129 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
130 EXPECT_EQ(nullptr, oat_file.get());
131}
132
Calin Juravle357c66d2017-05-04 01:57:17 +0000133// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
134// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
135TEST_F(OatFileAssistantTest, OdexUpToDate) {
136 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
137 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
138 Copy(GetDexSrc1(), dex_location);
139 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
140
141 // For the use of oat location by making the dex parent not writable.
142 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
143
144 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
145 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
146 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
147 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
148 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
149 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
150 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
151 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
152
153 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
154 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
155 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
156 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
157}
158
159// Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex
160// file via a symlink.
161// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
162TEST_F(OatFileAssistantTest, OdexUpToDateSymLink) {
163 std::string scratch_dir = GetScratchDir();
164 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar";
165 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex";
166
167 Copy(GetDexSrc1(), dex_location);
168 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
169
170 // Now replace the dex location with a symlink.
171 std::string link = scratch_dir + "/link";
172 ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str()));
173 dex_location = link + "/OdexUpToDate.jar";
174
175 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
176
177 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
178 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
179 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
180 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
181 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
182 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
183 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
184 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
185
186 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
187 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
188 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
189 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
190}
191
Richard Uhler66d874d2015-01-15 09:37:19 -0800192// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700193// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800194TEST_F(OatFileAssistantTest, OatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000195 if (IsExecutedAsRoot()) {
196 // We cannot simulate non writable locations when executed as root: b/38000545.
197 LOG(ERROR) << "Test skipped because it's running as root";
198 return;
199 }
200
Richard Uhler66d874d2015-01-15 09:37:19 -0800201 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
202 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000203 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800204
Calin Juravle357c66d2017-05-04 01:57:17 +0000205 // For the use of oat location by making the dex parent not writable.
206 ScopedNonWritable scoped_non_writable(dex_location);
207 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
208
209 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
210
211 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
212 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
213 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
214 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
215 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
216 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
217 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
218 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
219
220 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
221 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
222 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
223 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
224}
225
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700226// Case: Passing valid file descriptors of updated odex/vdex filesalong with
227// the dex file.
228// Expect: The status is kNoDexOptNeeded.
229TEST_F(OatFileAssistantTest, GetDexOptNeededWithFd) {
230 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
231 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
232 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
233
234 Copy(GetDexSrc1(), dex_location);
235 GenerateOatForTest(dex_location.c_str(),
236 odex_location.c_str(),
237 CompilerFilter::kSpeed,
238 true,
239 false,
240 false);
241
242 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY));
243 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700244 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700245
246 OatFileAssistant oat_file_assistant(dex_location.c_str(),
247 kRuntimeISA,
248 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000249 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700250 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700251 odex_fd.get(),
252 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700253 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
254 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
255 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
256 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
257 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
258 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
259 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
260 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
261
262 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
263 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
264 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
265 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
266}
267
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700268// Case: Passing invalid odex fd and valid vdex and zip fds.
269// Expect: The status should be kDex2OatForBootImage.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700270TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
271 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
272 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
273 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
274
275 Copy(GetDexSrc1(), dex_location);
276 GenerateOatForTest(dex_location.c_str(),
277 odex_location.c_str(),
278 CompilerFilter::kSpeed,
279 true,
280 false,
281 false);
282
283 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700284 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700285
286 OatFileAssistant oat_file_assistant(dex_location.c_str(),
287 kRuntimeISA,
288 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000289 false,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700290 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700291 -1 /* oat_fd */,
292 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700293 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
294 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700295 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
296 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
297
298 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700299 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
300 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700301 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700302}
303
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700304// Case: Passing invalid vdex fd and valid odex and zip fds.
305// Expect: The status should be kDex2OatFromScratch.
306TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
307 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
308 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
309
310 Copy(GetDexSrc1(), dex_location);
311 GenerateOatForTest(dex_location.c_str(),
312 odex_location.c_str(),
313 CompilerFilter::kSpeed,
314 true,
315 false,
316 false);
317
318 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY));
319 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
320
321 OatFileAssistant oat_file_assistant(dex_location.c_str(),
322 kRuntimeISA,
323 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000324 false,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700325 -1 /* vdex_fd */,
326 odex_fd.get(),
327 zip_fd.get());
328
329 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
330 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
331 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
332 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
333 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
334 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
335}
336
337// Case: Passing invalid vdex and odex fd with valid zip fd.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700338// Expect: The status is kDex2oatFromScratch.
339TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
340 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
341
342 Copy(GetDexSrc1(), dex_location);
343
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700344 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700345 OatFileAssistant oat_file_assistant(dex_location.c_str(),
346 kRuntimeISA,
347 false,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000348 false,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700349 -1 /* vdex_fd */,
350 -1 /* oat_fd */,
351 zip_fd);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700352 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
353 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
354 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
355 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
356}
357
Richard Uhler2f27abd2017-01-31 14:02:34 +0000358// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
359// ODEX file.
360TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000361 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000362 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000363
Richard Uhler9a37efc2016-08-05 16:32:55 -0700364 Copy(GetDexSrc1(), dex_location);
365
Richard Uhler2f27abd2017-01-31 14:02:34 +0000366 // Generating and deleting the oat file should have the side effect of
367 // creating an up-to-date vdex file.
Calin Juravle357c66d2017-05-04 01:57:17 +0000368 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
369 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000370
Calin Juravle357c66d2017-05-04 01:57:17 +0000371 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000372
373 // Even though the vdex file is up to date, because we don't have the oat
374 // file, we can't know that the vdex depends on the boot image and is up to
375 // date with respect to the boot image. Instead we must assume the vdex file
376 // depends on the boot image and is out of date with respect to the boot
377 // image.
378 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
379 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
380
381 // Make sure we don't crash in this case when we dump the status. We don't
382 // care what the actual dumped value is.
383 oat_file_assistant.GetStatusDump();
384}
385
386// Case: We have a DEX file and empty VDEX and ODEX files.
387TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
388 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
389 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
390 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
391
392 Copy(GetDexSrc1(), dex_location);
Richard Uhler5cd59292017-02-01 12:54:23 +0000393 ScratchFile vdex_file(vdex_location.c_str());
394 ScratchFile odex_file(odex_location.c_str());
Richard Uhler2f27abd2017-01-31 14:02:34 +0000395
396 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
397 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
398 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
399}
400
401// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
402// file.
403TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000404 if (IsExecutedAsRoot()) {
405 // We cannot simulate non writable locations when executed as root: b/38000545.
406 LOG(ERROR) << "Test skipped because it's running as root";
407 return;
408 }
Richard Uhler2f27abd2017-01-31 14:02:34 +0000409
410 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
411 std::string oat_location;
412 std::string error_msg;
413 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
414 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
415
416 Copy(GetDexSrc1(), dex_location);
417 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
418 ASSERT_EQ(0, unlink(oat_location.c_str()));
419
Calin Juravle357c66d2017-05-04 01:57:17 +0000420 ScopedNonWritable scoped_non_writable(dex_location);
421 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700422 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
423
Richard Uhler2f27abd2017-01-31 14:02:34 +0000424 // Even though the vdex file is up to date, because we don't have the oat
425 // file, we can't know that the vdex depends on the boot image and is up to
426 // date with respect to the boot image. Instead we must assume the vdex file
427 // depends on the boot image and is out of date with respect to the boot
428 // image.
429 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700430 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700431}
432
Andreas Gampe29d38e72016-03-23 15:31:51 +0000433// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700434// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
435// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000436TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000437 if (IsExecutedAsRoot()) {
438 // We cannot simulate non writable locations when executed as root: b/38000545.
439 LOG(ERROR) << "Test skipped because it's running as root";
440 return;
441 }
442
Andreas Gampe29d38e72016-03-23 15:31:51 +0000443 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
444 Copy(GetDexSrc1(), dex_location);
445 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
446
Calin Juravle357c66d2017-05-04 01:57:17 +0000447 ScopedNonWritable scoped_non_writable(dex_location);
448 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
449
Richard Uhlerd1472a22016-04-15 15:18:56 -0700450 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000451
452 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700453 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000454 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100455 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000456 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700457 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000458 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100459 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000460
461 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000462 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000463 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
464 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
465}
466
Richard Uhler66d874d2015-01-15 09:37:19 -0800467// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700468// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800469TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000470 if (IsExecutedAsRoot()) {
471 // We cannot simulate non writable locations when executed as root: b/38000545.
472 LOG(ERROR) << "Test skipped because it's running as root";
473 return;
474 }
475
Richard Uhler66d874d2015-01-15 09:37:19 -0800476 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
477 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000478 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800479
Calin Juravle357c66d2017-05-04 01:57:17 +0000480 ScopedNonWritable scoped_non_writable(dex_location);
481 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
482
Richard Uhlerd1472a22016-04-15 15:18:56 -0700483 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000484 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700485 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700486 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700487
488 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700489 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800490 ASSERT_TRUE(oat_file.get() != nullptr);
491 EXPECT_TRUE(oat_file->IsExecutable());
492 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700493 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
494 EXPECT_EQ(2u, dex_files.size());
495}
496
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000497// Case: We have a MultiDEX file where the non-main multdex entry is out of date.
Richard Uhler67ff7d12015-05-14 13:21:13 -0700498// Expect: The status is kDex2OatNeeded.
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000499TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000500 if (IsExecutedAsRoot()) {
501 // We cannot simulate non writable locations when executed as root: b/38000545.
502 LOG(ERROR) << "Test skipped because it's running as root";
503 return;
504 }
505
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000506 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
Richard Uhler67ff7d12015-05-14 13:21:13 -0700507
508 // Compile code for GetMultiDexSrc1.
509 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000510 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700511
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000512 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
Richard Uhler67ff7d12015-05-14 13:21:13 -0700513 // is out of date.
514 Copy(GetMultiDexSrc2(), dex_location);
515
Calin Juravle357c66d2017-05-04 01:57:17 +0000516 ScopedNonWritable scoped_non_writable(dex_location);
517 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
518
Richard Uhlerd1472a22016-04-15 15:18:56 -0700519 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000520 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700521 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700522 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700523}
524
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000525// Case: We have a stripped MultiDEX file where the non-main multidex entry is
526// out of date with respect to the odex file.
527TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
528 std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
529 std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
530
531 // Compile the oat from GetMultiDexSrc1.
532 Copy(GetMultiDexSrc1(), dex_location);
533 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
534
535 // Compile the odex from GetMultiDexSrc2, which has a different non-main
536 // dex checksum.
537 Copy(GetMultiDexSrc2(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100538 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000539
540 // Strip the dex file.
541 Copy(GetStrippedDexSrc1(), dex_location);
542
543 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable*/false);
544
545 // Because the dex file is stripped, the odex file is considered the source
546 // of truth for the dex checksums. The oat file should be considered
547 // unusable.
548 std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
549 ASSERT_TRUE(best_file.get() != nullptr);
550 EXPECT_EQ(best_file->GetLocation(), odex_location);
551 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
552 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
553 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
554}
555
Calin Juravle357c66d2017-05-04 01:57:17 +0000556// Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
Richard Uhlere5fed032015-03-18 08:21:11 -0700557// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700558// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700559TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
560 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000561 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
Richard Uhlere5fed032015-03-18 08:21:11 -0700562
563 // Create the dex file
564 Copy(GetMultiDexSrc1(), dex_location);
565
566 // Create the oat file with relative encoded dex location.
567 std::vector<std::string> args;
568 args.push_back("--dex-file=" + dex_location);
569 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
Calin Juravle357c66d2017-05-04 01:57:17 +0000570 args.push_back("--oat-file=" + odex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000571 args.push_back("--compiler-filter=speed");
Richard Uhlere5fed032015-03-18 08:21:11 -0700572
573 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700574 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700575
576 // Verify we can load both dex files.
Calin Juravle357c66d2017-05-04 01:57:17 +0000577 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
578
Richard Uhlere5fed032015-03-18 08:21:11 -0700579 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
580 ASSERT_TRUE(oat_file.get() != nullptr);
581 EXPECT_TRUE(oat_file->IsExecutable());
582 std::vector<std::unique_ptr<const DexFile>> dex_files;
583 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800584 EXPECT_EQ(2u, dex_files.size());
585}
586
Richard Uhler03bc6592016-11-22 09:42:04 +0000587// Case: We have a DEX file and an OAT file out of date with respect to the
588// dex checksum.
589TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000590 if (IsExecutedAsRoot()) {
591 // We cannot simulate non writable locations when executed as root: b/38000545.
592 LOG(ERROR) << "Test skipped because it's running as root";
593 return;
594 }
595
Richard Uhler03bc6592016-11-22 09:42:04 +0000596 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800597
598 // We create a dex, generate an oat for it, then overwrite the dex with a
599 // different dex to make the oat out of date.
600 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000601 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800602 Copy(GetDexSrc2(), dex_location);
603
Calin Juravle357c66d2017-05-04 01:57:17 +0000604 ScopedNonWritable scoped_non_writable(dex_location);
605 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
606
Richard Uhlerd1472a22016-04-15 15:18:56 -0700607 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000608 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100609 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000610 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000611 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800612
613 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000614 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
615 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
616 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
617}
618
Richard Uhler2f27abd2017-01-31 14:02:34 +0000619// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
620// to the dex checksum, but no ODEX file.
621TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000622 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000623 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000624
625 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000626 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
627 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000628 Copy(GetDexSrc2(), dex_location);
629
Calin Juravle357c66d2017-05-04 01:57:17 +0000630 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000631
632 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
633 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
634}
635
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000636// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
637// is out of date and there is no corresponding ODEX file.
638TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000639 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000640 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000641
642 Copy(GetMultiDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000643 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
644 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000645 Copy(GetMultiDexSrc2(), dex_location);
646
Calin Juravle357c66d2017-05-04 01:57:17 +0000647 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000648
649 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
650 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
651}
652
Richard Uhler03bc6592016-11-22 09:42:04 +0000653// Case: We have a DEX file and an OAT file out of date with respect to the
654// boot image.
655TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000656 if (IsExecutedAsRoot()) {
657 // We cannot simulate non writable locations when executed as root: b/38000545.
658 LOG(ERROR) << "Test skipped because it's running as root";
659 return;
660 }
661
Richard Uhler03bc6592016-11-22 09:42:04 +0000662 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
663
664 Copy(GetDexSrc1(), dex_location);
665 GenerateOatForTest(dex_location.c_str(),
666 CompilerFilter::kSpeed,
667 /*relocate*/true,
668 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000669 /*with_alternate_image*/true);
670
Calin Juravle357c66d2017-05-04 01:57:17 +0000671 ScopedNonWritable scoped_non_writable(dex_location);
672 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
673
Richard Uhler03bc6592016-11-22 09:42:04 +0000674 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000675 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100676 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000677 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100678 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000679 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000680 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
681
682 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
683 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
684 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
685 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
686}
687
688// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
689// respect to the boot image.
690// It shouldn't matter that the OAT file is out of date, because it is
691// verify-at-runtime.
692TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000693 if (IsExecutedAsRoot()) {
694 // We cannot simulate non writable locations when executed as root: b/38000545.
695 LOG(ERROR) << "Test skipped because it's running as root";
696 return;
697 }
698
Richard Uhler03bc6592016-11-22 09:42:04 +0000699 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
700
701 Copy(GetDexSrc1(), dex_location);
702 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100703 CompilerFilter::kExtract,
Richard Uhler03bc6592016-11-22 09:42:04 +0000704 /*relocate*/true,
705 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000706 /*with_alternate_image*/true);
707
Calin Juravle357c66d2017-05-04 01:57:17 +0000708 ScopedNonWritable scoped_non_writable(dex_location);
709 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
710
Richard Uhler03bc6592016-11-22 09:42:04 +0000711 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
712 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100713 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000714 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100715 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler03bc6592016-11-22 09:42:04 +0000716
717 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
718 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
719 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700720 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800721}
722
723// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800724TEST_F(OatFileAssistantTest, DexOdexNoOat) {
725 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700726 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800727
728 // Create the dex and odex files
729 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000730 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800731
732 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700733 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800734
Andreas Gampe29d38e72016-03-23 15:31:51 +0000735 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100736 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler5923b522016-12-08 09:48:01 +0000737 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000738 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800739
740 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000741 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
742 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700743 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700744
745 // We should still be able to get the non-executable odex file to run from.
746 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
747 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800748}
749
Richard Uhler5923b522016-12-08 09:48:01 +0000750// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800751TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
752 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700753 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800754
755 // Create the dex and odex files
756 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000757 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800758
759 // Strip the dex file
760 Copy(GetStrippedDexSrc1(), dex_location);
761
762 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700763 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800764
Richard Uhler5923b522016-12-08 09:48:01 +0000765 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
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 Uhler5923b522016-12-08 09:48:01 +0000769 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000770 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700771 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800772
Richard Uhler66d874d2015-01-15 09:37:19 -0800773 // Verify we can load the dex files from it.
774 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
775 ASSERT_TRUE(oat_file.get() != nullptr);
776 EXPECT_TRUE(oat_file->IsExecutable());
777 std::vector<std::unique_ptr<const DexFile>> dex_files;
778 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
779 EXPECT_EQ(1u, dex_files.size());
780}
781
Richard Uhler5923b522016-12-08 09:48:01 +0000782// 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 -0800783TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
784 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700785 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800786
787 // Create the oat file from a different dex file so it looks out of date.
788 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000789 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800790
791 // Create the odex file
792 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000793 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800794
795 // Strip the dex file.
796 Copy(GetStrippedDexSrc1(), dex_location);
797
798 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700799 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800800
Andreas Gampe29d38e72016-03-23 15:31:51 +0000801 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100802 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000803 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
804 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Nicolas Geoffray08e9eed2017-04-25 17:36:51 +0100805 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, // Compiling from the .vdex file
Andreas Gampe29d38e72016-03-23 15:31:51 +0000806 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800807
808 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000809 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
810 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700811 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800812
813 // Verify we can load the dex files from it.
814 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
815 ASSERT_TRUE(oat_file.get() != nullptr);
816 EXPECT_TRUE(oat_file->IsExecutable());
817 std::vector<std::unique_ptr<const DexFile>> dex_files;
818 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
819 EXPECT_EQ(1u, dex_files.size());
820}
821
Richard Uhler9b994ea2015-06-24 08:44:19 -0700822// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
823// OAT file. Expect: The status is kNoDexOptNeeded.
824TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
825 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
826
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 Uhler9b994ea2015-06-24 08:44:19 -0700831
Andreas Gampe29d38e72016-03-23 15:31:51 +0000832 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
833 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
834 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100835 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000836 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100837 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700838
839 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000840 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
841 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700842 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
843
844 // Make the oat file up to date. This should have no effect.
845 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700846 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700847 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -0700848 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700849 error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700850
Andreas Gampe29d38e72016-03-23 15:31:51 +0000851 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
852 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700853
854 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000855 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
856 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700857 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
858}
859
Richard Uhler66d874d2015-01-15 09:37:19 -0800860// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
861// OAT files both have patch delta of 0.
Richard Uhler5923b522016-12-08 09:48:01 +0000862// Expect: It shouldn't crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800863TEST_F(OatFileAssistantTest, OdexOatOverlap) {
864 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700865 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800866
Calin Juravle357c66d2017-05-04 01:57:17 +0000867 // Create the dex, the odex and the oat files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800868 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000869 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle357c66d2017-05-04 01:57:17 +0000870 GenerateOatForTest(dex_location.c_str(),
871 CompilerFilter::kSpeed,
872 /*relocate*/false,
873 /*pic*/false,
874 /*with_alternate_image*/false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800875
876 // Verify things don't go bad.
Calin Juravle357c66d2017-05-04 01:57:17 +0000877 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800878
Calin Juravle357c66d2017-05-04 01:57:17 +0000879 // -kDex2OatForRelocation is expected rather than kDex2OatForRelocation
880 // based on the assumption that the odex location is more up-to-date than the oat
Richard Uhler70a84262016-11-08 16:51:51 +0000881 // location, even if they both need relocation.
Calin Juravle357c66d2017-05-04 01:57:17 +0000882 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000883 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800884
885 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000886 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
887 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700888 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800889
890 // Things aren't relocated, so it should fall back to interpreted.
891 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
892 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700893
Richard Uhler66d874d2015-01-15 09:37:19 -0800894 EXPECT_FALSE(oat_file->IsExecutable());
895 std::vector<std::unique_ptr<const DexFile>> dex_files;
896 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
897 EXPECT_EQ(1u, dex_files.size());
898}
899
Andreas Gampe29d38e72016-03-23 15:31:51 +0000900// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
901// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
902TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
903 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
904 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000905
906 // Create the dex and odex files
907 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100908 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000909
910 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700911 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000912
Andreas Gampe29d38e72016-03-23 15:31:51 +0000913 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100914 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000915 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000916 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000917
918 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000919 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000920 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000921 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
922}
923
Richard Uhler66d874d2015-01-15 09:37:19 -0800924// Case: We have a DEX file and up-to-date OAT file for it.
925// Expect: We should load an executable dex file.
926TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000927 if (IsExecutedAsRoot()) {
928 // We cannot simulate non writable locations when executed as root: b/38000545.
929 LOG(ERROR) << "Test skipped because it's running as root";
930 return;
931 }
932
Richard Uhler66d874d2015-01-15 09:37:19 -0800933 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
934
935 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000936 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800937
Calin Juravle357c66d2017-05-04 01:57:17 +0000938 ScopedNonWritable scoped_non_writable(dex_location);
939 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
940
Richard Uhler66d874d2015-01-15 09:37:19 -0800941 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700942 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000943
944 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
945 ASSERT_TRUE(oat_file.get() != nullptr);
946 EXPECT_TRUE(oat_file->IsExecutable());
947 std::vector<std::unique_ptr<const DexFile>> dex_files;
948 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
949 EXPECT_EQ(1u, dex_files.size());
950}
951
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100952// Case: We have a DEX file and up-to-date quicken OAT file for it.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000953// Expect: We should still load the oat file as executable.
954TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
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
Andreas Gampe29d38e72016-03-23 15:31:51 +0000961 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
962
963 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100964 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000965
Calin Juravle357c66d2017-05-04 01:57:17 +0000966 ScopedNonWritable scoped_non_writable(dex_location);
967 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
968
Andreas Gampe29d38e72016-03-23 15:31:51 +0000969 // 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);
Richard Uhler66d874d2015-01-15 09:37:19 -0800971
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
980// Case: We have a DEX file and up-to-date OAT file for it.
981// Expect: Loading non-executable should load the oat non-executable.
982TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
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
Richard Uhler66d874d2015-01-15 09:37:19 -0800989 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
990
991 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000992
993 ScopedNonWritable scoped_non_writable(dex_location);
994 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
995
Andreas Gampe29d38e72016-03-23 15:31:51 +0000996 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800997
998 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700999 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001000
1001 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1002 ASSERT_TRUE(oat_file.get() != nullptr);
1003 EXPECT_FALSE(oat_file->IsExecutable());
1004 std::vector<std::unique_ptr<const DexFile>> dex_files;
1005 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1006 EXPECT_EQ(1u, dex_files.size());
1007}
1008
Richard Uhler8327cf72015-10-13 16:34:59 -07001009// Case: We don't have a DEX file and can't write the oat file.
1010// Expect: We should fail to generate the oat file without crashing.
1011TEST_F(OatFileAssistantTest, GenNoDex) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001012 if (IsExecutedAsRoot()) {
1013 // We cannot simulate non writable locations when executed as root: b/38000545.
1014 LOG(ERROR) << "Test skipped because it's running as root";
1015 return;
1016 }
Richard Uhler8327cf72015-10-13 16:34:59 -07001017
Calin Juravle357c66d2017-05-04 01:57:17 +00001018 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
1019
1020 ScopedNonWritable scoped_non_writable(dex_location);
1021 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1022
1023 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -07001024 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001025 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Calin Juravle357c66d2017-05-04 01:57:17 +00001026 // We should get kUpdateSucceeded from MakeUpToDate since there's nothing
1027 // that can be done in this situation.
1028 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001029 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Calin Juravle357c66d2017-05-04 01:57:17 +00001030
1031 // Verify it didn't create an oat in the default location (dalvik-cache).
1032 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
1033 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus());
1034 // Verify it didn't create the odex file in the default location (../oat/isa/...odex)
1035 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OdexFileStatus());
Richard Uhler8327cf72015-10-13 16:34:59 -07001036}
1037
Richard Uhler66d874d2015-01-15 09:37:19 -08001038// Turn an absolute path into a path relative to the current working
1039// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -08001040static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001041 char buf[MAXPATHLEN];
1042 std::string cwd = getcwd(buf, MAXPATHLEN);
1043
1044 // Split the target and cwd paths into components.
1045 std::vector<std::string> target_path;
1046 std::vector<std::string> cwd_path;
1047 Split(target, '/', &target_path);
1048 Split(cwd, '/', &cwd_path);
1049
1050 // Reverse the path components, so we can use pop_back().
1051 std::reverse(target_path.begin(), target_path.end());
1052 std::reverse(cwd_path.begin(), cwd_path.end());
1053
1054 // Drop the common prefix of the paths. Because we reversed the path
1055 // components, this becomes the common suffix of target_path and cwd_path.
1056 while (!target_path.empty() && !cwd_path.empty()
1057 && target_path.back() == cwd_path.back()) {
1058 target_path.pop_back();
1059 cwd_path.pop_back();
1060 }
1061
1062 // For each element of the remaining cwd_path, add '..' to the beginning
1063 // of the target path. Because we reversed the path components, we add to
1064 // the end of target_path.
1065 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1066 target_path.push_back("..");
1067 }
1068
1069 // Reverse again to get the right path order, and join to get the result.
1070 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001071 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001072}
1073
1074// Case: Non-absolute path to Dex location.
1075// Expect: Not sure, but it shouldn't crash.
1076TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1077 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1078 Copy(GetDexSrc1(), abs_dex_location);
1079
1080 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -07001081 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001082
1083 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001084 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001085 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001086 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1087 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001088}
1089
1090// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001091// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001092TEST_F(OatFileAssistantTest, ShortDexLocation) {
1093 std::string dex_location = "/xx";
1094
Richard Uhlerd1472a22016-04-15 15:18:56 -07001095 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001096
1097 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001098 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1099 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001100 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1101 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001102 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001103
Richard Uhler9b994ea2015-06-24 08:44:19 -07001104 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -08001105 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001106 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -07001107 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001108 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -07001109 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -08001110}
1111
1112// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001113// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001114TEST_F(OatFileAssistantTest, LongDexExtension) {
1115 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1116 Copy(GetDexSrc1(), dex_location);
1117
Richard Uhlerd1472a22016-04-15 15:18:56 -07001118 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001119
Richard Uhler7225a8d2016-11-22 10:12:03 +00001120 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001121 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001122
1123 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001124 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1125 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001126}
1127
1128// A task to generate a dex location. Used by the RaceToGenerate test.
1129class RaceGenerateTask : public Task {
1130 public:
1131 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
Jeff Haof0192c82016-03-28 20:39:50 -07001132 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001133 {}
1134
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01001135 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001136 // Load the dex files, and save a pointer to the loaded oat file, so that
1137 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001138 std::vector<std::unique_ptr<const DexFile>> dex_files;
1139 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001140 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001141 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1142 dex_location_.c_str(),
Jeff Hao0cb17282017-07-12 14:51:49 -07001143 Runtime::Current()->GetSystemClassLoader(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001144 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001145 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001146 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001147 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -07001148 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
1149 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001150 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001151 }
1152
1153 const OatFile* GetLoadedOatFile() const {
1154 return loaded_oat_file_;
1155 }
1156
1157 private:
1158 std::string dex_location_;
1159 std::string oat_location_;
1160 const OatFile* loaded_oat_file_;
1161};
1162
1163// Test the case where multiple processes race to generate an oat file.
1164// This simulates multiple processes using multiple threads.
1165//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001166// We want unique Oat files to be loaded even when there is a race to load.
1167// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1168// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001169TEST_F(OatFileAssistantTest, RaceToGenerate) {
1170 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001171 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001172
Jeff Hao0cb17282017-07-12 14:51:49 -07001173 // Start the runtime to initialize the system's class loader.
1174 Thread::Current()->TransitionFromSuspendedToRunnable();
1175 runtime_->Start();
1176
Richard Uhler66d874d2015-01-15 09:37:19 -08001177 // We use the lib core dex file, because it's large, and hopefully should
1178 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001179 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001180
1181 const int kNumThreads = 32;
1182 Thread* self = Thread::Current();
1183 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1184 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1185 for (int i = 0; i < kNumThreads; i++) {
1186 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1187 thread_pool.AddTask(self, task.get());
1188 tasks.push_back(std::move(task));
1189 }
1190 thread_pool.StartWorkers(self);
1191 thread_pool.Wait(self, true, false);
1192
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001193 // Verify every task got a unique oat file.
1194 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001195 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001196 const OatFile* oat_file = task->GetLoadedOatFile();
1197 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1198 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001199 }
1200}
1201
1202// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1203// disabled.
1204// Expect: We should load the odex file non-executable.
1205TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1206 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001207 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001208
1209 // Create the dex and odex files
1210 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001211 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001212
1213 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001214 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001215
1216 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1217 ASSERT_TRUE(oat_file.get() != nullptr);
1218 EXPECT_FALSE(oat_file->IsExecutable());
1219 std::vector<std::unique_ptr<const DexFile>> dex_files;
1220 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1221 EXPECT_EQ(1u, dex_files.size());
1222}
1223
1224// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1225// disabled.
1226// Expect: We should load the odex file non-executable.
1227TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1228 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001229 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001230
1231 // Create the dex and odex files
1232 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001233 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001234
1235 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001236 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001237
1238 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1239 ASSERT_TRUE(oat_file.get() != nullptr);
1240 EXPECT_FALSE(oat_file->IsExecutable());
1241 std::vector<std::unique_ptr<const DexFile>> dex_files;
1242 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1243 EXPECT_EQ(2u, dex_files.size());
1244}
1245
Richard Uhlerf4b34872016-04-13 11:03:46 -07001246TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
1247 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
1248 Copy(GetDexSrc1(), dex_location);
1249
Richard Uhlerd1472a22016-04-15 15:18:56 -07001250 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhlerf4b34872016-04-13 11:03:46 -07001251
1252 std::string error_msg;
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001253 Runtime::Current()->AddCompilerOption("--compiler-filter=quicken");
Richard Uhlerf4b34872016-04-13 11:03:46 -07001254 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001255 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001256 error_msg;
Calin Juravle357c66d2017-05-04 01:57:17 +00001257 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001258 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Calin Juravle357c66d2017-05-04 01:57:17 +00001259 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Richard Uhlerf4b34872016-04-13 11:03:46 -07001260 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1261
1262 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
1263 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001264 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg))
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001265 << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001266 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001267 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001268 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1269 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1270
1271 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
1272 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001273 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001274}
1275
Richard Uhlerb81881d2016-04-19 13:08:04 -07001276TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001277 std::string error_msg;
1278 std::string odex_file;
1279
Richard Uhlerb81881d2016-04-19 13:08:04 -07001280 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001281 "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001282 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001283
Richard Uhlerb81881d2016-04-19 13:08:04 -07001284 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001285 "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001286 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001287
Richard Uhlerb81881d2016-04-19 13:08:04 -07001288 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001289 "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001290 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001291 "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001292}
1293
Richard Uhler23cedd22015-04-08 13:17:29 -07001294// Verify the dexopt status values from dalvik.system.DexFile
1295// match the OatFileAssistant::DexOptStatus values.
1296TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001297 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1298 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1299 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1300 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1301 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
1302 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001303 };
1304
Richard Uhler23cedd22015-04-08 13:17:29 -07001305 ScopedObjectAccess soa(Thread::Current());
1306 StackHandleScope<1> hs(soa.Self());
1307 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1308 Handle<mirror::Class> dexfile(
1309 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
Andreas Gampefa4333d2017-02-14 11:10:34 -08001310 ASSERT_FALSE(dexfile == nullptr);
Richard Uhler23cedd22015-04-08 13:17:29 -07001311 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1312
Richard Uhler7225a8d2016-11-22 10:12:03 +00001313 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1314 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001315 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001316 ASSERT_FALSE(art_field == nullptr);
1317 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1318 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1319 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001320}
Richard Uhler66d874d2015-01-15 09:37:19 -08001321
Calin Juravle07c6d722017-06-07 17:06:12 +00001322// Verify that when no compiler filter is passed the default one from OatFileAssistant is used.
1323TEST_F(OatFileAssistantTest, DefaultMakeUpToDateFilter) {
1324 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1325 Copy(GetDexSrc1(), dex_location);
1326
1327 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1328
1329 const CompilerFilter::Filter default_filter =
1330 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1331 std::string error_msg;
1332 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001333 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001334 error_msg;
Calin Juravle07c6d722017-06-07 17:06:12 +00001335 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1336 oat_file_assistant.GetDexOptNeeded(default_filter));
1337 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1338 EXPECT_NE(nullptr, oat_file.get());
1339 EXPECT_EQ(default_filter, oat_file->GetCompilerFilter());
1340}
1341
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001342TEST_F(OatFileAssistantTest, MakeUpToDateWithSpecialSharedLibrary) {
1343 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1344 Copy(GetDexSrc1(), dex_location);
1345
1346 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1347
1348 const CompilerFilter::Filter default_filter =
1349 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1350 std::string error_msg;
Calin Juravle44e5efa2017-09-12 00:54:26 -07001351 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001352 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1353 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1354 oat_file_assistant.GetDexOptNeeded(default_filter));
1355 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1356 EXPECT_NE(nullptr, oat_file.get());
1357 EXPECT_EQ(kSpecialSharedLibrary,
1358 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1359}
1360
1361TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
1362 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1363 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1364 Copy(GetDexSrc1(), dex_location);
1365 Copy(GetDexSrc2(), context_location);
1366
1367 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1368
1369 const CompilerFilter::Filter default_filter =
1370 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1371 std::string error_msg;
1372 std::string context_str = "PCL[" + context_location + "]";
Calin Juravle44e5efa2017-09-12 00:54:26 -07001373 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1374 ASSERT_TRUE(context != nullptr);
1375 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1376
1377 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001378 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1379 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001380 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1381
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001382 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1383 EXPECT_NE(nullptr, oat_file.get());
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001384 EXPECT_EQ(context->EncodeContextForOatFile(""),
1385 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1386}
1387
Calin Juravle44e5efa2017-09-12 00:54:26 -07001388TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
1389 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1390 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1391 Copy(GetDexSrc1(), dex_location);
1392 Copy(GetDexSrc2(), context_location);
1393
1394 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1395
1396 const CompilerFilter::Filter default_filter =
1397 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1398 std::string error_msg;
1399 std::string context_str = "PCL[" + context_location + "]";
1400 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1401 ASSERT_TRUE(context != nullptr);
1402 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1403
1404 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1405 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1406 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1407 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1408
1409 // Update the context by overriding the jar file.
1410 Copy(GetMultiDexSrc2(), context_location);
1411 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1412 ASSERT_TRUE(updated_context != nullptr);
1413 // DexOptNeeded should advise compilation from scratch.
1414 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
1415 oat_file_assistant.GetDexOptNeeded(
1416 default_filter, false, false, updated_context.get()));
1417}
1418
Calin Juravle20c46442017-09-12 00:54:26 -07001419TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
1420 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1421 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1422 Copy(GetDexSrc1(), dex_location);
1423 Copy(GetDexSrc2(), context_location);
1424
1425 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1426
1427 const CompilerFilter::Filter default_filter =
1428 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1429 std::string error_msg;
1430 std::string context_str = "PCL[" + context_location + "]";
1431 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1432 ASSERT_TRUE(context != nullptr);
1433 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1434
1435 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1436 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1437
1438 // A relative context simulates a dependent split context.
1439 std::unique_ptr<ClassLoaderContext> relative_context =
1440 ClassLoaderContext::Create("PCL[ContextDex.jar]");
1441 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1442 oat_file_assistant.GetDexOptNeeded(
1443 default_filter, false, false, relative_context.get()));
1444}
1445
Nicolas Geoffray29742602017-12-14 10:09:03 +00001446TEST_F(OatFileAssistantTest, SystemOdex) {
1447 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
1448 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
1449 std::string system_location = GetAndroidRoot() + "/OatUpToDate.jar";
1450
1451 std::string error_msg;
1452
1453 Copy(GetDexSrc1(), dex_location);
1454 EXPECT_FALSE(LocationIsOnSystem(dex_location.c_str()));
1455
1456 {
1457 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1458 kRuntimeISA,
1459 true,
1460 false);
1461 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1462 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1463 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1464 }
1465
1466 {
1467 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1468 kRuntimeISA,
1469 true,
1470 true);
1471 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1472 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1473 EXPECT_FALSE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1474 }
1475
1476 Copy(GetDexSrc1(), system_location);
1477 EXPECT_TRUE(LocationIsOnSystem(system_location.c_str()));
1478
1479 {
1480 OatFileAssistant oat_file_assistant(system_location.c_str(),
1481 kRuntimeISA,
1482 true,
1483 false);
1484 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1485 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1486 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1487 }
1488
1489 {
1490 OatFileAssistant oat_file_assistant(system_location.c_str(),
1491 kRuntimeISA,
1492 true,
1493 true);
1494 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
1495 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1496 EXPECT_TRUE(oat_file_assistant.GetBestOatFile()->IsExecutable());
1497 }
1498}
1499
Richard Uhler66d874d2015-01-15 09:37:19 -08001500// TODO: More Tests:
1501// * Test class linker falls back to unquickened dex for DexNoOat
1502// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001503// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001504// * Test for status of oat while oat is being generated (how?)
1505// * Test case where 32 and 64 bit boot class paths differ,
1506// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1507// 64 bit boot class paths.
1508// * Test unexpected scenarios (?):
1509// - Dex is stripped, don't have odex.
1510// - Oat file corrupted after status check, before reload unexecutable
1511// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001512} // namespace art