blob: bd500ebe7750db58eb2302d4882959d05fa36e2f [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
Calin Juravle27e0d1f2017-07-26 00:16:07 -070043static const std::string kSpecialSharedLibrary = "&";
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,
249 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700250 odex_fd.get(),
251 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700252 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
253 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
254 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
255 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
256 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
257 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
258 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
259 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
260
261 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
262 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
263 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
264 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
265}
266
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700267// Case: Passing invalid odex fd and valid vdex and zip fds.
268// Expect: The status should be kDex2OatForBootImage.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700269TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
270 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
271 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
272 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
273
274 Copy(GetDexSrc1(), dex_location);
275 GenerateOatForTest(dex_location.c_str(),
276 odex_location.c_str(),
277 CompilerFilter::kSpeed,
278 true,
279 false,
280 false);
281
282 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700283 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700284
285 OatFileAssistant oat_file_assistant(dex_location.c_str(),
286 kRuntimeISA,
287 false,
288 vdex_fd.get(),
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700289 -1 /* oat_fd */,
290 zip_fd.get());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700291 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
292 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700293 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
294 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
295
296 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700297 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
298 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700299 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700300}
301
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700302// Case: Passing invalid vdex fd and valid odex and zip fds.
303// Expect: The status should be kDex2OatFromScratch.
304TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
305 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
306 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
307
308 Copy(GetDexSrc1(), dex_location);
309 GenerateOatForTest(dex_location.c_str(),
310 odex_location.c_str(),
311 CompilerFilter::kSpeed,
312 true,
313 false,
314 false);
315
316 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY));
317 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
318
319 OatFileAssistant oat_file_assistant(dex_location.c_str(),
320 kRuntimeISA,
321 false,
322 -1 /* vdex_fd */,
323 odex_fd.get(),
324 zip_fd.get());
325
326 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
327 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
328 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
329 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
330 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
331 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
332}
333
334// Case: Passing invalid vdex and odex fd with valid zip fd.
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700335// Expect: The status is kDex2oatFromScratch.
336TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
337 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
338
339 Copy(GetDexSrc1(), dex_location);
340
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700341 android::base::unique_fd zip_fd(open(dex_location.c_str(), O_RDONLY));
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700342 OatFileAssistant oat_file_assistant(dex_location.c_str(),
343 kRuntimeISA,
344 false,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700345 -1 /* vdex_fd */,
346 -1 /* oat_fd */,
347 zip_fd);
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700348 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
349 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
350 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
351 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
352}
353
Calin Juravle357c66d2017-05-04 01:57:17 +0000354// Case: We have a DEX file and up-to-date OAT file for it. We load the dex file
355// via a symlink.
356// Expect: The status is kNoDexOptNeeded.
357TEST_F(OatFileAssistantTest, OatUpToDateSymLink) {
358 if (IsExecutedAsRoot()) {
359 // We cannot simulate non writable locations when executed as root: b/38000545.
360 LOG(ERROR) << "Test skipped because it's running as root";
361 return;
362 }
363
364 std::string real = GetScratchDir() + "/real";
365 ASSERT_EQ(0, mkdir(real.c_str(), 0700));
366 std::string link = GetScratchDir() + "/link";
367 ASSERT_EQ(0, symlink(real.c_str(), link.c_str()));
368
369 std::string dex_location = real + "/OatUpToDate.jar";
370
371 Copy(GetDexSrc1(), dex_location);
372 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
373
374 // Update the dex location to point to the symlink.
375 dex_location = link + "/OatUpToDate.jar";
376
377 // For the use of oat location by making the dex parent not writable.
378 ScopedNonWritable scoped_non_writable(dex_location);
379 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
380
Richard Uhlerd1472a22016-04-15 15:18:56 -0700381 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800382
Andreas Gampe29d38e72016-03-23 15:31:51 +0000383 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
384 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
385 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100386 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000387 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100388 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000389 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000390 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
391
Richard Uhler66d874d2015-01-15 09:37:19 -0800392 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000393 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Richard Uhler95abd042015-03-24 09:51:28 -0700394 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700395 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800396}
397
Richard Uhler2f27abd2017-01-31 14:02:34 +0000398// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
399// ODEX file.
400TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
401 // This test case is only meaningful if vdex is enabled.
402 if (!kIsVdexEnabled) {
403 return;
404 }
Richard Uhler9a37efc2016-08-05 16:32:55 -0700405
Richard Uhler2f27abd2017-01-31 14:02:34 +0000406 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000407 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000408
Richard Uhler9a37efc2016-08-05 16:32:55 -0700409 Copy(GetDexSrc1(), dex_location);
410
Richard Uhler2f27abd2017-01-31 14:02:34 +0000411 // Generating and deleting the oat file should have the side effect of
412 // creating an up-to-date vdex file.
Calin Juravle357c66d2017-05-04 01:57:17 +0000413 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
414 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000415
Calin Juravle357c66d2017-05-04 01:57:17 +0000416 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000417
418 // Even though the vdex file is up to date, because we don't have the oat
419 // file, we can't know that the vdex depends on the boot image and is up to
420 // date with respect to the boot image. Instead we must assume the vdex file
421 // depends on the boot image and is out of date with respect to the boot
422 // image.
423 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
424 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
425
426 // Make sure we don't crash in this case when we dump the status. We don't
427 // care what the actual dumped value is.
428 oat_file_assistant.GetStatusDump();
429}
430
431// Case: We have a DEX file and empty VDEX and ODEX files.
432TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
433 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
434 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
435 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
436
437 Copy(GetDexSrc1(), dex_location);
Richard Uhler5cd59292017-02-01 12:54:23 +0000438 ScratchFile vdex_file(vdex_location.c_str());
439 ScratchFile odex_file(odex_location.c_str());
Richard Uhler2f27abd2017-01-31 14:02:34 +0000440
441 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
442 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
443 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
444}
445
446// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
447// file.
448TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
449 // This test case is only meaningful if vdex is enabled.
450 if (!kIsVdexEnabled) {
451 return;
452 }
Calin Juravle357c66d2017-05-04 01:57:17 +0000453 if (IsExecutedAsRoot()) {
454 // We cannot simulate non writable locations when executed as root: b/38000545.
455 LOG(ERROR) << "Test skipped because it's running as root";
456 return;
457 }
Richard Uhler2f27abd2017-01-31 14:02:34 +0000458
459 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
460 std::string oat_location;
461 std::string error_msg;
462 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
463 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
464
465 Copy(GetDexSrc1(), dex_location);
466 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
467 ASSERT_EQ(0, unlink(oat_location.c_str()));
468
Calin Juravle357c66d2017-05-04 01:57:17 +0000469 ScopedNonWritable scoped_non_writable(dex_location);
470 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700471 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
472
Richard Uhler2f27abd2017-01-31 14:02:34 +0000473 // Even though the vdex file is up to date, because we don't have the oat
474 // file, we can't know that the vdex depends on the boot image and is up to
475 // date with respect to the boot image. Instead we must assume the vdex file
476 // depends on the boot image and is out of date with respect to the boot
477 // image.
478 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700479 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700480}
481
Andreas Gampe29d38e72016-03-23 15:31:51 +0000482// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700483// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
484// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000485TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000486 if (IsExecutedAsRoot()) {
487 // We cannot simulate non writable locations when executed as root: b/38000545.
488 LOG(ERROR) << "Test skipped because it's running as root";
489 return;
490 }
491
Andreas Gampe29d38e72016-03-23 15:31:51 +0000492 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
493 Copy(GetDexSrc1(), dex_location);
494 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
495
Calin Juravle357c66d2017-05-04 01:57:17 +0000496 ScopedNonWritable scoped_non_writable(dex_location);
497 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
498
Richard Uhlerd1472a22016-04-15 15:18:56 -0700499 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000500
501 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700502 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000503 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100504 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000505 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700506 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000507 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100508 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000509
510 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000511 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000512 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
513 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
514}
515
Richard Uhler66d874d2015-01-15 09:37:19 -0800516// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700517// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800518TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000519 if (IsExecutedAsRoot()) {
520 // We cannot simulate non writable locations when executed as root: b/38000545.
521 LOG(ERROR) << "Test skipped because it's running as root";
522 return;
523 }
524
Richard Uhler66d874d2015-01-15 09:37:19 -0800525 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
526 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000527 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800528
Calin Juravle357c66d2017-05-04 01:57:17 +0000529 ScopedNonWritable scoped_non_writable(dex_location);
530 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
531
Richard Uhlerd1472a22016-04-15 15:18:56 -0700532 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000533 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700534 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700535 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700536
537 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700538 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800539 ASSERT_TRUE(oat_file.get() != nullptr);
540 EXPECT_TRUE(oat_file->IsExecutable());
541 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700542 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
543 EXPECT_EQ(2u, dex_files.size());
544}
545
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000546// Case: We have a MultiDEX file where the non-main multdex entry is out of date.
Richard Uhler67ff7d12015-05-14 13:21:13 -0700547// Expect: The status is kDex2OatNeeded.
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000548TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000549 if (IsExecutedAsRoot()) {
550 // We cannot simulate non writable locations when executed as root: b/38000545.
551 LOG(ERROR) << "Test skipped because it's running as root";
552 return;
553 }
554
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000555 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
Richard Uhler67ff7d12015-05-14 13:21:13 -0700556
557 // Compile code for GetMultiDexSrc1.
558 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000559 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700560
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000561 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
Richard Uhler67ff7d12015-05-14 13:21:13 -0700562 // is out of date.
563 Copy(GetMultiDexSrc2(), dex_location);
564
Calin Juravle357c66d2017-05-04 01:57:17 +0000565 ScopedNonWritable scoped_non_writable(dex_location);
566 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
567
Richard Uhlerd1472a22016-04-15 15:18:56 -0700568 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000569 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700570 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700571 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700572}
573
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000574// Case: We have a stripped MultiDEX file where the non-main multidex entry is
575// out of date with respect to the odex file.
576TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
577 std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
578 std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
579
580 // Compile the oat from GetMultiDexSrc1.
581 Copy(GetMultiDexSrc1(), dex_location);
582 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
583
584 // Compile the odex from GetMultiDexSrc2, which has a different non-main
585 // dex checksum.
586 Copy(GetMultiDexSrc2(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100587 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000588
589 // Strip the dex file.
590 Copy(GetStrippedDexSrc1(), dex_location);
591
592 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable*/false);
593
594 // Because the dex file is stripped, the odex file is considered the source
595 // of truth for the dex checksums. The oat file should be considered
596 // unusable.
597 std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
598 ASSERT_TRUE(best_file.get() != nullptr);
599 EXPECT_EQ(best_file->GetLocation(), odex_location);
600 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
601 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
602 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
603}
604
Calin Juravle357c66d2017-05-04 01:57:17 +0000605// Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
Richard Uhlere5fed032015-03-18 08:21:11 -0700606// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700607// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700608TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
609 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000610 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
Richard Uhlere5fed032015-03-18 08:21:11 -0700611
612 // Create the dex file
613 Copy(GetMultiDexSrc1(), dex_location);
614
615 // Create the oat file with relative encoded dex location.
616 std::vector<std::string> args;
617 args.push_back("--dex-file=" + dex_location);
618 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
Calin Juravle357c66d2017-05-04 01:57:17 +0000619 args.push_back("--oat-file=" + odex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000620 args.push_back("--compiler-filter=speed");
Richard Uhlere5fed032015-03-18 08:21:11 -0700621
622 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700623 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700624
625 // Verify we can load both dex files.
Calin Juravle357c66d2017-05-04 01:57:17 +0000626 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
627
Richard Uhlere5fed032015-03-18 08:21:11 -0700628 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
629 ASSERT_TRUE(oat_file.get() != nullptr);
630 EXPECT_TRUE(oat_file->IsExecutable());
631 std::vector<std::unique_ptr<const DexFile>> dex_files;
632 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800633 EXPECT_EQ(2u, dex_files.size());
634}
635
Richard Uhler03bc6592016-11-22 09:42:04 +0000636// Case: We have a DEX file and an OAT file out of date with respect to the
637// dex checksum.
638TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000639 if (IsExecutedAsRoot()) {
640 // We cannot simulate non writable locations when executed as root: b/38000545.
641 LOG(ERROR) << "Test skipped because it's running as root";
642 return;
643 }
644
Richard Uhler03bc6592016-11-22 09:42:04 +0000645 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800646
647 // We create a dex, generate an oat for it, then overwrite the dex with a
648 // different dex to make the oat out of date.
649 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000650 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800651 Copy(GetDexSrc2(), dex_location);
652
Calin Juravle357c66d2017-05-04 01:57:17 +0000653 ScopedNonWritable scoped_non_writable(dex_location);
654 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
655
Richard Uhlerd1472a22016-04-15 15:18:56 -0700656 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000657 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100658 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000659 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000660 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800661
662 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000663 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
664 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
665 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
666}
667
Richard Uhler2f27abd2017-01-31 14:02:34 +0000668// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
669// to the dex checksum, but no ODEX file.
670TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
671 // This test case is only meaningful if vdex is enabled.
672 if (!kIsVdexEnabled) {
673 return;
674 }
675
676 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000677 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000678
679 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000680 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
681 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000682 Copy(GetDexSrc2(), dex_location);
683
Calin Juravle357c66d2017-05-04 01:57:17 +0000684 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000685
686 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
687 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
688}
689
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000690// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
691// is out of date and there is no corresponding ODEX file.
692TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000693 // This test case is only meaningful if vdex is enabled.
694 if (!kIsVdexEnabled) {
695 return;
696 }
697
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000698 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000699 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000700
701 Copy(GetMultiDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000702 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
703 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000704 Copy(GetMultiDexSrc2(), dex_location);
705
Calin Juravle357c66d2017-05-04 01:57:17 +0000706 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000707
708 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
709 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
710}
711
Richard Uhler03bc6592016-11-22 09:42:04 +0000712// Case: We have a DEX file and an OAT file out of date with respect to the
713// boot image.
714TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000715 if (IsExecutedAsRoot()) {
716 // We cannot simulate non writable locations when executed as root: b/38000545.
717 LOG(ERROR) << "Test skipped because it's running as root";
718 return;
719 }
720
Richard Uhler03bc6592016-11-22 09:42:04 +0000721 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
722
723 Copy(GetDexSrc1(), dex_location);
724 GenerateOatForTest(dex_location.c_str(),
725 CompilerFilter::kSpeed,
726 /*relocate*/true,
727 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000728 /*with_alternate_image*/true);
729
Calin Juravle357c66d2017-05-04 01:57:17 +0000730 ScopedNonWritable scoped_non_writable(dex_location);
731 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
732
Richard Uhler03bc6592016-11-22 09:42:04 +0000733 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000734 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100735 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000736 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100737 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000738 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000739 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
740
741 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
742 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
743 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
744 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
745}
746
747// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
748// respect to the boot image.
749// It shouldn't matter that the OAT file is out of date, because it is
750// verify-at-runtime.
751TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000752 if (IsExecutedAsRoot()) {
753 // We cannot simulate non writable locations when executed as root: b/38000545.
754 LOG(ERROR) << "Test skipped because it's running as root";
755 return;
756 }
757
Richard Uhler03bc6592016-11-22 09:42:04 +0000758 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
759
760 Copy(GetDexSrc1(), dex_location);
761 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100762 CompilerFilter::kExtract,
Richard Uhler03bc6592016-11-22 09:42:04 +0000763 /*relocate*/true,
764 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000765 /*with_alternate_image*/true);
766
Calin Juravle357c66d2017-05-04 01:57:17 +0000767 ScopedNonWritable scoped_non_writable(dex_location);
768 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
769
Richard Uhler03bc6592016-11-22 09:42:04 +0000770 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
771 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100772 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000773 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100774 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler03bc6592016-11-22 09:42:04 +0000775
776 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
777 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
778 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700779 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800780}
781
782// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800783TEST_F(OatFileAssistantTest, DexOdexNoOat) {
784 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700785 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800786
787 // Create the dex and odex files
788 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000789 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800790
791 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700792 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800793
Andreas Gampe29d38e72016-03-23 15:31:51 +0000794 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100795 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler5923b522016-12-08 09:48:01 +0000796 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000797 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800798
799 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000800 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
801 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700802 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700803
804 // We should still be able to get the non-executable odex file to run from.
805 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
806 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800807}
808
Richard Uhler5923b522016-12-08 09:48:01 +0000809// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800810TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
811 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700812 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800813
814 // Create the dex and odex files
815 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000816 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800817
818 // Strip the dex file
819 Copy(GetStrippedDexSrc1(), dex_location);
820
821 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700822 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800823
Richard Uhler5923b522016-12-08 09:48:01 +0000824 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000825 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800826
827 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000828 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000829 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700830 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800831
Richard Uhler66d874d2015-01-15 09:37:19 -0800832 // Verify we can load the dex files from it.
833 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
834 ASSERT_TRUE(oat_file.get() != nullptr);
835 EXPECT_TRUE(oat_file->IsExecutable());
836 std::vector<std::unique_ptr<const DexFile>> dex_files;
837 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
838 EXPECT_EQ(1u, dex_files.size());
839}
840
Richard Uhler5923b522016-12-08 09:48:01 +0000841// 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 -0800842TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
843 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700844 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800845
846 // Create the oat file from a different dex file so it looks out of date.
847 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000848 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800849
850 // Create the odex file
851 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000852 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800853
854 // Strip the dex file.
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 Uhler66d874d2015-01-15 09:37:19 -0800859
Andreas Gampe29d38e72016-03-23 15:31:51 +0000860 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100861 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000862 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
863 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Nicolas Geoffray08e9eed2017-04-25 17:36:51 +0100864 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, // Compiling from the .vdex file
Andreas Gampe29d38e72016-03-23 15:31:51 +0000865 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800866
867 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000868 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
869 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700870 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800871
872 // Verify we can load the dex files from it.
873 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
874 ASSERT_TRUE(oat_file.get() != nullptr);
875 EXPECT_TRUE(oat_file->IsExecutable());
876 std::vector<std::unique_ptr<const DexFile>> dex_files;
877 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
878 EXPECT_EQ(1u, dex_files.size());
879}
880
Richard Uhler9b994ea2015-06-24 08:44:19 -0700881// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
882// OAT file. Expect: The status is kNoDexOptNeeded.
883TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
884 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
885
886 Copy(GetStrippedDexSrc1(), dex_location);
887
888 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700889 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700890
Andreas Gampe29d38e72016-03-23 15:31:51 +0000891 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
892 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
893 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100894 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000895 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100896 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700897
898 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000899 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
900 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700901 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
902
903 // Make the oat file up to date. This should have no effect.
904 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700905 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700906 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -0700907 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700908 error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700909
Andreas Gampe29d38e72016-03-23 15:31:51 +0000910 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
911 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700912
913 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000914 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
915 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700916 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
917}
918
Richard Uhler66d874d2015-01-15 09:37:19 -0800919// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
920// OAT files both have patch delta of 0.
Richard Uhler5923b522016-12-08 09:48:01 +0000921// Expect: It shouldn't crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800922TEST_F(OatFileAssistantTest, OdexOatOverlap) {
923 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700924 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800925
Calin Juravle357c66d2017-05-04 01:57:17 +0000926 // Create the dex, the odex and the oat files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800927 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000928 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle357c66d2017-05-04 01:57:17 +0000929 GenerateOatForTest(dex_location.c_str(),
930 CompilerFilter::kSpeed,
931 /*relocate*/false,
932 /*pic*/false,
933 /*with_alternate_image*/false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800934
935 // Verify things don't go bad.
Calin Juravle357c66d2017-05-04 01:57:17 +0000936 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800937
Calin Juravle357c66d2017-05-04 01:57:17 +0000938 // -kDex2OatForRelocation is expected rather than kDex2OatForRelocation
939 // based on the assumption that the odex location is more up-to-date than the oat
Richard Uhler70a84262016-11-08 16:51:51 +0000940 // location, even if they both need relocation.
Calin Juravle357c66d2017-05-04 01:57:17 +0000941 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000942 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800943
944 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000945 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
946 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700947 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800948
949 // Things aren't relocated, so it should fall back to interpreted.
950 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
951 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700952
Richard Uhler66d874d2015-01-15 09:37:19 -0800953 EXPECT_FALSE(oat_file->IsExecutable());
954 std::vector<std::unique_ptr<const DexFile>> dex_files;
955 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
956 EXPECT_EQ(1u, dex_files.size());
957}
958
Andreas Gampe29d38e72016-03-23 15:31:51 +0000959// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
960// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
961TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
962 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
963 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000964
965 // Create the dex and odex files
966 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100967 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000968
969 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700970 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000971
Andreas Gampe29d38e72016-03-23 15:31:51 +0000972 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100973 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000974 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000975 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000976
977 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000978 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000979 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000980 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
981}
982
Richard Uhler66d874d2015-01-15 09:37:19 -0800983// Case: We have a DEX file and up-to-date OAT file for it.
984// Expect: We should load an executable dex file.
985TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000986 if (IsExecutedAsRoot()) {
987 // We cannot simulate non writable locations when executed as root: b/38000545.
988 LOG(ERROR) << "Test skipped because it's running as root";
989 return;
990 }
991
Richard Uhler66d874d2015-01-15 09:37:19 -0800992 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
993
994 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000995 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800996
Calin Juravle357c66d2017-05-04 01:57:17 +0000997 ScopedNonWritable scoped_non_writable(dex_location);
998 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
999
Richard Uhler66d874d2015-01-15 09:37:19 -08001000 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001001 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001002
1003 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1004 ASSERT_TRUE(oat_file.get() != nullptr);
1005 EXPECT_TRUE(oat_file->IsExecutable());
1006 std::vector<std::unique_ptr<const DexFile>> dex_files;
1007 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1008 EXPECT_EQ(1u, dex_files.size());
1009}
1010
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001011// Case: We have a DEX file and up-to-date quicken OAT file for it.
Andreas Gampe29d38e72016-03-23 15:31:51 +00001012// Expect: We should still load the oat file as executable.
1013TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001014 if (IsExecutedAsRoot()) {
1015 // We cannot simulate non writable locations when executed as root: b/38000545.
1016 LOG(ERROR) << "Test skipped because it's running as root";
1017 return;
1018 }
1019
Andreas Gampe29d38e72016-03-23 15:31:51 +00001020 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
1021
1022 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001023 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001024
Calin Juravle357c66d2017-05-04 01:57:17 +00001025 ScopedNonWritable scoped_non_writable(dex_location);
1026 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1027
Andreas Gampe29d38e72016-03-23 15:31:51 +00001028 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001029 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001030
1031 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1032 ASSERT_TRUE(oat_file.get() != nullptr);
1033 EXPECT_TRUE(oat_file->IsExecutable());
1034 std::vector<std::unique_ptr<const DexFile>> dex_files;
1035 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1036 EXPECT_EQ(1u, dex_files.size());
1037}
1038
1039// Case: We have a DEX file and up-to-date OAT file for it.
1040// Expect: Loading non-executable should load the oat non-executable.
1041TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001042 if (IsExecutedAsRoot()) {
1043 // We cannot simulate non writable locations when executed as root: b/38000545.
1044 LOG(ERROR) << "Test skipped because it's running as root";
1045 return;
1046 }
1047
Richard Uhler66d874d2015-01-15 09:37:19 -08001048 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
1049
1050 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +00001051
1052 ScopedNonWritable scoped_non_writable(dex_location);
1053 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1054
Andreas Gampe29d38e72016-03-23 15:31:51 +00001055 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001056
1057 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001058 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001059
1060 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1061 ASSERT_TRUE(oat_file.get() != nullptr);
1062 EXPECT_FALSE(oat_file->IsExecutable());
1063 std::vector<std::unique_ptr<const DexFile>> dex_files;
1064 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1065 EXPECT_EQ(1u, dex_files.size());
1066}
1067
Richard Uhler8327cf72015-10-13 16:34:59 -07001068// Case: We don't have a DEX file and can't write the oat file.
1069// Expect: We should fail to generate the oat file without crashing.
1070TEST_F(OatFileAssistantTest, GenNoDex) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001071 if (IsExecutedAsRoot()) {
1072 // We cannot simulate non writable locations when executed as root: b/38000545.
1073 LOG(ERROR) << "Test skipped because it's running as root";
1074 return;
1075 }
Richard Uhler8327cf72015-10-13 16:34:59 -07001076
Calin Juravle357c66d2017-05-04 01:57:17 +00001077 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
1078
1079 ScopedNonWritable scoped_non_writable(dex_location);
1080 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1081
1082 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -07001083 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001084 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Calin Juravle357c66d2017-05-04 01:57:17 +00001085 // We should get kUpdateSucceeded from MakeUpToDate since there's nothing
1086 // that can be done in this situation.
1087 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001088 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Calin Juravle357c66d2017-05-04 01:57:17 +00001089
1090 // Verify it didn't create an oat in the default location (dalvik-cache).
1091 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
1092 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus());
1093 // Verify it didn't create the odex file in the default location (../oat/isa/...odex)
1094 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OdexFileStatus());
Richard Uhler8327cf72015-10-13 16:34:59 -07001095}
1096
Richard Uhler66d874d2015-01-15 09:37:19 -08001097// Turn an absolute path into a path relative to the current working
1098// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -08001099static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001100 char buf[MAXPATHLEN];
1101 std::string cwd = getcwd(buf, MAXPATHLEN);
1102
1103 // Split the target and cwd paths into components.
1104 std::vector<std::string> target_path;
1105 std::vector<std::string> cwd_path;
1106 Split(target, '/', &target_path);
1107 Split(cwd, '/', &cwd_path);
1108
1109 // Reverse the path components, so we can use pop_back().
1110 std::reverse(target_path.begin(), target_path.end());
1111 std::reverse(cwd_path.begin(), cwd_path.end());
1112
1113 // Drop the common prefix of the paths. Because we reversed the path
1114 // components, this becomes the common suffix of target_path and cwd_path.
1115 while (!target_path.empty() && !cwd_path.empty()
1116 && target_path.back() == cwd_path.back()) {
1117 target_path.pop_back();
1118 cwd_path.pop_back();
1119 }
1120
1121 // For each element of the remaining cwd_path, add '..' to the beginning
1122 // of the target path. Because we reversed the path components, we add to
1123 // the end of target_path.
1124 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1125 target_path.push_back("..");
1126 }
1127
1128 // Reverse again to get the right path order, and join to get the result.
1129 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001130 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001131}
1132
1133// Case: Non-absolute path to Dex location.
1134// Expect: Not sure, but it shouldn't crash.
1135TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1136 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1137 Copy(GetDexSrc1(), abs_dex_location);
1138
1139 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -07001140 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001141
1142 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001143 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001144 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001145 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1146 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001147}
1148
1149// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001150// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001151TEST_F(OatFileAssistantTest, ShortDexLocation) {
1152 std::string dex_location = "/xx";
1153
Richard Uhlerd1472a22016-04-15 15:18:56 -07001154 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001155
1156 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001157 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1158 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001159 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1160 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001161 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001162
Richard Uhler9b994ea2015-06-24 08:44:19 -07001163 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -08001164 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001165 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -07001166 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001167 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -07001168 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -08001169}
1170
1171// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001172// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001173TEST_F(OatFileAssistantTest, LongDexExtension) {
1174 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1175 Copy(GetDexSrc1(), dex_location);
1176
Richard Uhlerd1472a22016-04-15 15:18:56 -07001177 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001178
Richard Uhler7225a8d2016-11-22 10:12:03 +00001179 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001180 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001181
1182 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001183 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1184 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001185}
1186
1187// A task to generate a dex location. Used by the RaceToGenerate test.
1188class RaceGenerateTask : public Task {
1189 public:
1190 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
Jeff Haof0192c82016-03-28 20:39:50 -07001191 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001192 {}
1193
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01001194 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001195 // Load the dex files, and save a pointer to the loaded oat file, so that
1196 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001197 std::vector<std::unique_ptr<const DexFile>> dex_files;
1198 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001199 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001200 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1201 dex_location_.c_str(),
Jeff Hao0cb17282017-07-12 14:51:49 -07001202 Runtime::Current()->GetSystemClassLoader(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001203 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001204 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001205 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001206 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -07001207 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
1208 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001209 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001210 }
1211
1212 const OatFile* GetLoadedOatFile() const {
1213 return loaded_oat_file_;
1214 }
1215
1216 private:
1217 std::string dex_location_;
1218 std::string oat_location_;
1219 const OatFile* loaded_oat_file_;
1220};
1221
1222// Test the case where multiple processes race to generate an oat file.
1223// This simulates multiple processes using multiple threads.
1224//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001225// We want unique Oat files to be loaded even when there is a race to load.
1226// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1227// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001228TEST_F(OatFileAssistantTest, RaceToGenerate) {
1229 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001230 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001231
Jeff Hao0cb17282017-07-12 14:51:49 -07001232 // Start the runtime to initialize the system's class loader.
1233 Thread::Current()->TransitionFromSuspendedToRunnable();
1234 runtime_->Start();
1235
Richard Uhler66d874d2015-01-15 09:37:19 -08001236 // We use the lib core dex file, because it's large, and hopefully should
1237 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001238 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001239
1240 const int kNumThreads = 32;
1241 Thread* self = Thread::Current();
1242 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1243 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1244 for (int i = 0; i < kNumThreads; i++) {
1245 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1246 thread_pool.AddTask(self, task.get());
1247 tasks.push_back(std::move(task));
1248 }
1249 thread_pool.StartWorkers(self);
1250 thread_pool.Wait(self, true, false);
1251
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001252 // Verify every task got a unique oat file.
1253 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001254 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001255 const OatFile* oat_file = task->GetLoadedOatFile();
1256 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1257 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001258 }
1259}
1260
1261// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1262// disabled.
1263// Expect: We should load the odex file non-executable.
1264TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1265 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001266 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001267
1268 // Create the dex and odex files
1269 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001270 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001271
1272 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001273 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001274
1275 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1276 ASSERT_TRUE(oat_file.get() != nullptr);
1277 EXPECT_FALSE(oat_file->IsExecutable());
1278 std::vector<std::unique_ptr<const DexFile>> dex_files;
1279 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1280 EXPECT_EQ(1u, dex_files.size());
1281}
1282
1283// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1284// disabled.
1285// Expect: We should load the odex file non-executable.
1286TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1287 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001288 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001289
1290 // Create the dex and odex files
1291 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001292 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001293
1294 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001295 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001296
1297 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1298 ASSERT_TRUE(oat_file.get() != nullptr);
1299 EXPECT_FALSE(oat_file->IsExecutable());
1300 std::vector<std::unique_ptr<const DexFile>> dex_files;
1301 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1302 EXPECT_EQ(2u, dex_files.size());
1303}
1304
Richard Uhlerf4b34872016-04-13 11:03:46 -07001305TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
1306 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
1307 Copy(GetDexSrc1(), dex_location);
1308
Richard Uhlerd1472a22016-04-15 15:18:56 -07001309 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhlerf4b34872016-04-13 11:03:46 -07001310
1311 std::string error_msg;
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001312 Runtime::Current()->AddCompilerOption("--compiler-filter=quicken");
Richard Uhlerf4b34872016-04-13 11:03:46 -07001313 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001314 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001315 error_msg;
Calin Juravle357c66d2017-05-04 01:57:17 +00001316 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001317 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Calin Juravle357c66d2017-05-04 01:57:17 +00001318 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Richard Uhlerf4b34872016-04-13 11:03:46 -07001319 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1320
1321 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
1322 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001323 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg))
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001324 << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001325 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001326 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001327 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1328 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1329
1330 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
1331 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001332 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001333}
1334
Richard Uhlerb81881d2016-04-19 13:08:04 -07001335TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001336 std::string error_msg;
1337 std::string odex_file;
1338
Richard Uhlerb81881d2016-04-19 13:08:04 -07001339 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001340 "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001341 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001342
Richard Uhlerb81881d2016-04-19 13:08:04 -07001343 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001344 "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001345 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001346
Richard Uhlerb81881d2016-04-19 13:08:04 -07001347 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001348 "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001349 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001350 "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001351}
1352
Richard Uhler23cedd22015-04-08 13:17:29 -07001353// Verify the dexopt status values from dalvik.system.DexFile
1354// match the OatFileAssistant::DexOptStatus values.
1355TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001356 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1357 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1358 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1359 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1360 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
1361 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001362 };
1363
Richard Uhler23cedd22015-04-08 13:17:29 -07001364 ScopedObjectAccess soa(Thread::Current());
1365 StackHandleScope<1> hs(soa.Self());
1366 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1367 Handle<mirror::Class> dexfile(
1368 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
Andreas Gampefa4333d2017-02-14 11:10:34 -08001369 ASSERT_FALSE(dexfile == nullptr);
Richard Uhler23cedd22015-04-08 13:17:29 -07001370 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1371
Richard Uhler7225a8d2016-11-22 10:12:03 +00001372 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1373 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001374 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001375 ASSERT_FALSE(art_field == nullptr);
1376 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1377 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1378 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001379}
Richard Uhler66d874d2015-01-15 09:37:19 -08001380
Calin Juravle07c6d722017-06-07 17:06:12 +00001381// Verify that when no compiler filter is passed the default one from OatFileAssistant is used.
1382TEST_F(OatFileAssistantTest, DefaultMakeUpToDateFilter) {
1383 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1384 Copy(GetDexSrc1(), dex_location);
1385
1386 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1387
1388 const CompilerFilter::Filter default_filter =
1389 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1390 std::string error_msg;
1391 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001392 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001393 error_msg;
Calin Juravle07c6d722017-06-07 17:06:12 +00001394 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1395 oat_file_assistant.GetDexOptNeeded(default_filter));
1396 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1397 EXPECT_NE(nullptr, oat_file.get());
1398 EXPECT_EQ(default_filter, oat_file->GetCompilerFilter());
1399}
1400
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001401TEST_F(OatFileAssistantTest, MakeUpToDateWithSpecialSharedLibrary) {
1402 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1403 Copy(GetDexSrc1(), dex_location);
1404
1405 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1406
1407 const CompilerFilter::Filter default_filter =
1408 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1409 std::string error_msg;
Calin Juravle44e5efa2017-09-12 00:54:26 -07001410 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001411 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1412 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1413 oat_file_assistant.GetDexOptNeeded(default_filter));
1414 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1415 EXPECT_NE(nullptr, oat_file.get());
1416 EXPECT_EQ(kSpecialSharedLibrary,
1417 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1418}
1419
1420TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
1421 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1422 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1423 Copy(GetDexSrc1(), dex_location);
1424 Copy(GetDexSrc2(), context_location);
1425
1426 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1427
1428 const CompilerFilter::Filter default_filter =
1429 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1430 std::string error_msg;
1431 std::string context_str = "PCL[" + context_location + "]";
Calin Juravle44e5efa2017-09-12 00:54:26 -07001432 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1433 ASSERT_TRUE(context != nullptr);
1434 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1435
1436 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001437 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1438 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001439 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1440
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001441 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1442 EXPECT_NE(nullptr, oat_file.get());
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001443 EXPECT_EQ(context->EncodeContextForOatFile(""),
1444 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1445}
1446
Calin Juravle44e5efa2017-09-12 00:54:26 -07001447TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
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 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1466 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1467
1468 // Update the context by overriding the jar file.
1469 Copy(GetMultiDexSrc2(), context_location);
1470 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1471 ASSERT_TRUE(updated_context != nullptr);
1472 // DexOptNeeded should advise compilation from scratch.
1473 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
1474 oat_file_assistant.GetDexOptNeeded(
1475 default_filter, false, false, updated_context.get()));
1476}
1477
Calin Juravle20c46442017-09-12 00:54:26 -07001478TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
1479 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1480 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1481 Copy(GetDexSrc1(), dex_location);
1482 Copy(GetDexSrc2(), context_location);
1483
1484 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1485
1486 const CompilerFilter::Filter default_filter =
1487 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1488 std::string error_msg;
1489 std::string context_str = "PCL[" + context_location + "]";
1490 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1491 ASSERT_TRUE(context != nullptr);
1492 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1493
1494 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1495 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1496
1497 // A relative context simulates a dependent split context.
1498 std::unique_ptr<ClassLoaderContext> relative_context =
1499 ClassLoaderContext::Create("PCL[ContextDex.jar]");
1500 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1501 oat_file_assistant.GetDexOptNeeded(
1502 default_filter, false, false, relative_context.get()));
1503}
1504
Richard Uhler66d874d2015-01-15 09:37:19 -08001505// TODO: More Tests:
1506// * Test class linker falls back to unquickened dex for DexNoOat
1507// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001508// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001509// * Test for status of oat while oat is being generated (how?)
1510// * Test case where 32 and 64 bit boot class paths differ,
1511// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1512// 64 bit boot class paths.
1513// * Test unexpected scenarios (?):
1514// - Dex is stripped, don't have odex.
1515// - Oat file corrupted after status check, before reload unexecutable
1516// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001517} // namespace art