blob: d12c33180132370c64c64b162ec0e0914f3f38fb [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));
244
245 OatFileAssistant oat_file_assistant(dex_location.c_str(),
246 kRuntimeISA,
247 false,
248 vdex_fd.get(),
249 odex_fd.get());
250 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
251 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
252 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
253 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
254 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
255 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
256 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
257 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
258
259 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
260 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
261 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
262 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
263}
264
265// Case: Passing valid odex fd, however, invalid fd for vdex with
266// the dex file.
267// Expect: The status is kDex2oatFromScratch.
268TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidVdexFd) {
269 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
270 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
271
272 Copy(GetDexSrc1(), dex_location);
273 GenerateOatForTest(dex_location.c_str(),
274 odex_location.c_str(),
275 CompilerFilter::kSpeed,
276 true,
277 false,
278 false);
279
280 android::base::unique_fd odex_fd(open(odex_location.c_str(), O_RDONLY));
281
282 OatFileAssistant oat_file_assistant(dex_location.c_str(),
283 kRuntimeISA,
284 false,
285 -1,
286 odex_fd.get());
287 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
288 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
289 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
290 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
291}
292
293// Case: Passing valid vdex fd, however, invalid fd for odex with
294// the dex file.
295// Expect: The status is kDex2oatFromScratch.
296TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexFd) {
297 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
298 std::string odex_location = GetScratchDir() + "/OatUpToDate.odex";
299 std::string vdex_location = GetScratchDir() + "/OatUpToDate.vdex";
300
301 Copy(GetDexSrc1(), dex_location);
302 GenerateOatForTest(dex_location.c_str(),
303 odex_location.c_str(),
304 CompilerFilter::kSpeed,
305 true,
306 false,
307 false);
308
309 android::base::unique_fd vdex_fd(open(vdex_location.c_str(), O_RDONLY));
310
311 OatFileAssistant oat_file_assistant(dex_location.c_str(),
312 kRuntimeISA,
313 false,
314 vdex_fd.get(),
315 -1);
316 // Even though the vdex file is up to date, because we don't have the oat
317 // file, we can't know that the vdex depends on the boot image and is up to
318 // date with respect to the boot image. Instead we must assume the vdex file
319 // depends on the boot image and is out of date with respect to the boot
320 // image.
321 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
322 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
323 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OdexFileStatus());
324 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
325}
326
327// Case: Passing invalid vdex and odex fd with the dex file.
328// Expect: The status is kDex2oatFromScratch.
329TEST_F(OatFileAssistantTest, GetDexOptNeededWithInvalidOdexVdexFd) {
330 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
331
332 Copy(GetDexSrc1(), dex_location);
333
334 OatFileAssistant oat_file_assistant(dex_location.c_str(),
335 kRuntimeISA,
336 false,
337 -1,
338 -1);
339 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
340 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
341 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
342 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
343}
344
Calin Juravle357c66d2017-05-04 01:57:17 +0000345// Case: We have a DEX file and up-to-date OAT file for it. We load the dex file
346// via a symlink.
347// Expect: The status is kNoDexOptNeeded.
348TEST_F(OatFileAssistantTest, OatUpToDateSymLink) {
349 if (IsExecutedAsRoot()) {
350 // We cannot simulate non writable locations when executed as root: b/38000545.
351 LOG(ERROR) << "Test skipped because it's running as root";
352 return;
353 }
354
355 std::string real = GetScratchDir() + "/real";
356 ASSERT_EQ(0, mkdir(real.c_str(), 0700));
357 std::string link = GetScratchDir() + "/link";
358 ASSERT_EQ(0, symlink(real.c_str(), link.c_str()));
359
360 std::string dex_location = real + "/OatUpToDate.jar";
361
362 Copy(GetDexSrc1(), dex_location);
363 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
364
365 // Update the dex location to point to the symlink.
366 dex_location = link + "/OatUpToDate.jar";
367
368 // For the use of oat location by making the dex parent not writable.
369 ScopedNonWritable scoped_non_writable(dex_location);
370 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
371
Richard Uhlerd1472a22016-04-15 15:18:56 -0700372 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800373
Andreas Gampe29d38e72016-03-23 15:31:51 +0000374 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
375 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
376 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100377 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000378 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100379 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000380 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000381 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
382
Richard Uhler66d874d2015-01-15 09:37:19 -0800383 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000384 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Richard Uhler95abd042015-03-24 09:51:28 -0700385 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700386 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800387}
388
Richard Uhler2f27abd2017-01-31 14:02:34 +0000389// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
390// ODEX file.
391TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
392 // This test case is only meaningful if vdex is enabled.
393 if (!kIsVdexEnabled) {
394 return;
395 }
Richard Uhler9a37efc2016-08-05 16:32:55 -0700396
Richard Uhler2f27abd2017-01-31 14:02:34 +0000397 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000398 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000399
Richard Uhler9a37efc2016-08-05 16:32:55 -0700400 Copy(GetDexSrc1(), dex_location);
401
Richard Uhler2f27abd2017-01-31 14:02:34 +0000402 // Generating and deleting the oat file should have the side effect of
403 // creating an up-to-date vdex file.
Calin Juravle357c66d2017-05-04 01:57:17 +0000404 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
405 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000406
Calin Juravle357c66d2017-05-04 01:57:17 +0000407 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000408
409 // Even though the vdex file is up to date, because we don't have the oat
410 // file, we can't know that the vdex depends on the boot image and is up to
411 // date with respect to the boot image. Instead we must assume the vdex file
412 // depends on the boot image and is out of date with respect to the boot
413 // image.
414 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
415 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
416
417 // Make sure we don't crash in this case when we dump the status. We don't
418 // care what the actual dumped value is.
419 oat_file_assistant.GetStatusDump();
420}
421
422// Case: We have a DEX file and empty VDEX and ODEX files.
423TEST_F(OatFileAssistantTest, EmptyVdexOdex) {
424 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar";
425 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat";
426 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex";
427
428 Copy(GetDexSrc1(), dex_location);
Richard Uhler5cd59292017-02-01 12:54:23 +0000429 ScratchFile vdex_file(vdex_location.c_str());
430 ScratchFile odex_file(odex_location.c_str());
Richard Uhler2f27abd2017-01-31 14:02:34 +0000431
432 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
433 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
434 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
435}
436
437// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
438// file.
439TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
440 // This test case is only meaningful if vdex is enabled.
441 if (!kIsVdexEnabled) {
442 return;
443 }
Calin Juravle357c66d2017-05-04 01:57:17 +0000444 if (IsExecutedAsRoot()) {
445 // We cannot simulate non writable locations when executed as root: b/38000545.
446 LOG(ERROR) << "Test skipped because it's running as root";
447 return;
448 }
Richard Uhler2f27abd2017-01-31 14:02:34 +0000449
450 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
451 std::string oat_location;
452 std::string error_msg;
453 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
454 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
455
456 Copy(GetDexSrc1(), dex_location);
457 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
458 ASSERT_EQ(0, unlink(oat_location.c_str()));
459
Calin Juravle357c66d2017-05-04 01:57:17 +0000460 ScopedNonWritable scoped_non_writable(dex_location);
461 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700462 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
463
Richard Uhler2f27abd2017-01-31 14:02:34 +0000464 // Even though the vdex file is up to date, because we don't have the oat
465 // file, we can't know that the vdex depends on the boot image and is up to
466 // date with respect to the boot image. Instead we must assume the vdex file
467 // depends on the boot image and is out of date with respect to the boot
468 // image.
469 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700470 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700471}
472
Andreas Gampe29d38e72016-03-23 15:31:51 +0000473// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700474// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
475// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000476TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000477 if (IsExecutedAsRoot()) {
478 // We cannot simulate non writable locations when executed as root: b/38000545.
479 LOG(ERROR) << "Test skipped because it's running as root";
480 return;
481 }
482
Andreas Gampe29d38e72016-03-23 15:31:51 +0000483 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
484 Copy(GetDexSrc1(), dex_location);
485 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
486
Calin Juravle357c66d2017-05-04 01:57:17 +0000487 ScopedNonWritable scoped_non_writable(dex_location);
488 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
489
Richard Uhlerd1472a22016-04-15 15:18:56 -0700490 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000491
492 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700493 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000494 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100495 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000496 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700497 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000498 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100499 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000500
501 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000502 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000503 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
504 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
505}
506
Richard Uhler66d874d2015-01-15 09:37:19 -0800507// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700508// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800509TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000510 if (IsExecutedAsRoot()) {
511 // We cannot simulate non writable locations when executed as root: b/38000545.
512 LOG(ERROR) << "Test skipped because it's running as root";
513 return;
514 }
515
Richard Uhler66d874d2015-01-15 09:37:19 -0800516 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
517 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000518 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800519
Calin Juravle357c66d2017-05-04 01:57:17 +0000520 ScopedNonWritable scoped_non_writable(dex_location);
521 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
522
Richard Uhlerd1472a22016-04-15 15:18:56 -0700523 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000524 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700525 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700526 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700527
528 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700529 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800530 ASSERT_TRUE(oat_file.get() != nullptr);
531 EXPECT_TRUE(oat_file->IsExecutable());
532 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700533 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
534 EXPECT_EQ(2u, dex_files.size());
535}
536
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000537// Case: We have a MultiDEX file where the non-main multdex entry is out of date.
Richard Uhler67ff7d12015-05-14 13:21:13 -0700538// Expect: The status is kDex2OatNeeded.
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000539TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000540 if (IsExecutedAsRoot()) {
541 // We cannot simulate non writable locations when executed as root: b/38000545.
542 LOG(ERROR) << "Test skipped because it's running as root";
543 return;
544 }
545
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000546 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar";
Richard Uhler67ff7d12015-05-14 13:21:13 -0700547
548 // Compile code for GetMultiDexSrc1.
549 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000550 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700551
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000552 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum
Richard Uhler67ff7d12015-05-14 13:21:13 -0700553 // is out of date.
554 Copy(GetMultiDexSrc2(), dex_location);
555
Calin Juravle357c66d2017-05-04 01:57:17 +0000556 ScopedNonWritable scoped_non_writable(dex_location);
557 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
558
Richard Uhlerd1472a22016-04-15 15:18:56 -0700559 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000560 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700561 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700562 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700563}
564
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000565// Case: We have a stripped MultiDEX file where the non-main multidex entry is
566// out of date with respect to the odex file.
567TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) {
568 std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar";
569 std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex";
570
571 // Compile the oat from GetMultiDexSrc1.
572 Copy(GetMultiDexSrc1(), dex_location);
573 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
574
575 // Compile the odex from GetMultiDexSrc2, which has a different non-main
576 // dex checksum.
577 Copy(GetMultiDexSrc2(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100578 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken);
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000579
580 // Strip the dex file.
581 Copy(GetStrippedDexSrc1(), dex_location);
582
583 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable*/false);
584
585 // Because the dex file is stripped, the odex file is considered the source
586 // of truth for the dex checksums. The oat file should be considered
587 // unusable.
588 std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile();
589 ASSERT_TRUE(best_file.get() != nullptr);
590 EXPECT_EQ(best_file->GetLocation(), odex_location);
591 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
592 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
593 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
594}
595
Calin Juravle357c66d2017-05-04 01:57:17 +0000596// Case: We have a MultiDEX file and up-to-date ODEX file for it with relative
Richard Uhlere5fed032015-03-18 08:21:11 -0700597// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700598// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700599TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
600 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000601 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex";
Richard Uhlere5fed032015-03-18 08:21:11 -0700602
603 // Create the dex file
604 Copy(GetMultiDexSrc1(), dex_location);
605
606 // Create the oat file with relative encoded dex location.
607 std::vector<std::string> args;
608 args.push_back("--dex-file=" + dex_location);
609 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
Calin Juravle357c66d2017-05-04 01:57:17 +0000610 args.push_back("--oat-file=" + odex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000611 args.push_back("--compiler-filter=speed");
Richard Uhlere5fed032015-03-18 08:21:11 -0700612
613 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700614 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700615
616 // Verify we can load both dex files.
Calin Juravle357c66d2017-05-04 01:57:17 +0000617 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
618
Richard Uhlere5fed032015-03-18 08:21:11 -0700619 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
620 ASSERT_TRUE(oat_file.get() != nullptr);
621 EXPECT_TRUE(oat_file->IsExecutable());
622 std::vector<std::unique_ptr<const DexFile>> dex_files;
623 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800624 EXPECT_EQ(2u, dex_files.size());
625}
626
Richard Uhler03bc6592016-11-22 09:42:04 +0000627// Case: We have a DEX file and an OAT file out of date with respect to the
628// dex checksum.
629TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000630 if (IsExecutedAsRoot()) {
631 // We cannot simulate non writable locations when executed as root: b/38000545.
632 LOG(ERROR) << "Test skipped because it's running as root";
633 return;
634 }
635
Richard Uhler03bc6592016-11-22 09:42:04 +0000636 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800637
638 // We create a dex, generate an oat for it, then overwrite the dex with a
639 // different dex to make the oat out of date.
640 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000641 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800642 Copy(GetDexSrc2(), dex_location);
643
Calin Juravle357c66d2017-05-04 01:57:17 +0000644 ScopedNonWritable scoped_non_writable(dex_location);
645 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
646
Richard Uhlerd1472a22016-04-15 15:18:56 -0700647 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000648 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100649 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000650 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000651 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800652
653 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000654 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
655 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
656 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
657}
658
Richard Uhler2f27abd2017-01-31 14:02:34 +0000659// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
660// to the dex checksum, but no ODEX file.
661TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
662 // This test case is only meaningful if vdex is enabled.
663 if (!kIsVdexEnabled) {
664 return;
665 }
666
667 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000668 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000669
670 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000671 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
672 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000673 Copy(GetDexSrc2(), dex_location);
674
Calin Juravle357c66d2017-05-04 01:57:17 +0000675 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000676
677 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
678 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
679}
680
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000681// Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry
682// is out of date and there is no corresponding ODEX file.
683TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) {
Richard Uhler2f27abd2017-01-31 14:02:34 +0000684 // This test case is only meaningful if vdex is enabled.
685 if (!kIsVdexEnabled) {
686 return;
687 }
688
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000689 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar";
Calin Juravle357c66d2017-05-04 01:57:17 +0000690 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex";
Richard Uhler2f27abd2017-01-31 14:02:34 +0000691
692 Copy(GetMultiDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +0000693 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
694 ASSERT_EQ(0, unlink(odex_location.c_str()));
Richard Uhler2f27abd2017-01-31 14:02:34 +0000695 Copy(GetMultiDexSrc2(), dex_location);
696
Calin Juravle357c66d2017-05-04 01:57:17 +0000697 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler2f27abd2017-01-31 14:02:34 +0000698
699 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
700 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
701}
702
Richard Uhler03bc6592016-11-22 09:42:04 +0000703// Case: We have a DEX file and an OAT file out of date with respect to the
704// boot image.
705TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000706 if (IsExecutedAsRoot()) {
707 // We cannot simulate non writable locations when executed as root: b/38000545.
708 LOG(ERROR) << "Test skipped because it's running as root";
709 return;
710 }
711
Richard Uhler03bc6592016-11-22 09:42:04 +0000712 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
713
714 Copy(GetDexSrc1(), dex_location);
715 GenerateOatForTest(dex_location.c_str(),
716 CompilerFilter::kSpeed,
717 /*relocate*/true,
718 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000719 /*with_alternate_image*/true);
720
Calin Juravle357c66d2017-05-04 01:57:17 +0000721 ScopedNonWritable scoped_non_writable(dex_location);
722 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
723
Richard Uhler03bc6592016-11-22 09:42:04 +0000724 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000725 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100726 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000727 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100728 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000729 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000730 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
731
732 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
733 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
734 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
735 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
736}
737
738// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
739// respect to the boot image.
740// It shouldn't matter that the OAT file is out of date, because it is
741// verify-at-runtime.
742TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000743 if (IsExecutedAsRoot()) {
744 // We cannot simulate non writable locations when executed as root: b/38000545.
745 LOG(ERROR) << "Test skipped because it's running as root";
746 return;
747 }
748
Richard Uhler03bc6592016-11-22 09:42:04 +0000749 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
750
751 Copy(GetDexSrc1(), dex_location);
752 GenerateOatForTest(dex_location.c_str(),
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100753 CompilerFilter::kExtract,
Richard Uhler03bc6592016-11-22 09:42:04 +0000754 /*relocate*/true,
755 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000756 /*with_alternate_image*/true);
757
Calin Juravle357c66d2017-05-04 01:57:17 +0000758 ScopedNonWritable scoped_non_writable(dex_location);
759 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
760
Richard Uhler03bc6592016-11-22 09:42:04 +0000761 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
762 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100763 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000764 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100765 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler03bc6592016-11-22 09:42:04 +0000766
767 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
768 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
769 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700770 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800771}
772
773// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800774TEST_F(OatFileAssistantTest, DexOdexNoOat) {
775 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700776 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800777
778 // Create the dex and odex files
779 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000780 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800781
782 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700783 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800784
Andreas Gampe29d38e72016-03-23 15:31:51 +0000785 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100786 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler5923b522016-12-08 09:48:01 +0000787 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000788 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800789
790 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000791 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
792 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700793 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700794
795 // We should still be able to get the non-executable odex file to run from.
796 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
797 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800798}
799
Richard Uhler5923b522016-12-08 09:48:01 +0000800// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800801TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
802 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700803 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800804
805 // Create the dex and odex files
806 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000807 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800808
809 // Strip the dex file
810 Copy(GetStrippedDexSrc1(), dex_location);
811
812 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700813 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800814
Richard Uhler5923b522016-12-08 09:48:01 +0000815 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000816 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800817
818 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000819 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000820 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700821 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800822
Richard Uhler66d874d2015-01-15 09:37:19 -0800823 // Verify we can load the dex files from it.
824 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
825 ASSERT_TRUE(oat_file.get() != nullptr);
826 EXPECT_TRUE(oat_file->IsExecutable());
827 std::vector<std::unique_ptr<const DexFile>> dex_files;
828 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
829 EXPECT_EQ(1u, dex_files.size());
830}
831
Richard Uhler5923b522016-12-08 09:48:01 +0000832// 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 -0800833TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
834 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700835 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800836
837 // Create the oat file from a different dex file so it looks out of date.
838 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000839 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800840
841 // Create the odex file
842 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000843 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800844
845 // Strip the dex file.
846 Copy(GetStrippedDexSrc1(), dex_location);
847
848 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700849 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800850
Andreas Gampe29d38e72016-03-23 15:31:51 +0000851 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100852 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000853 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
854 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Nicolas Geoffray08e9eed2017-04-25 17:36:51 +0100855 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, // Compiling from the .vdex file
Andreas Gampe29d38e72016-03-23 15:31:51 +0000856 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800857
858 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000859 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
860 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700861 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800862
863 // Verify we can load the dex files from it.
864 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
865 ASSERT_TRUE(oat_file.get() != nullptr);
866 EXPECT_TRUE(oat_file->IsExecutable());
867 std::vector<std::unique_ptr<const DexFile>> dex_files;
868 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
869 EXPECT_EQ(1u, dex_files.size());
870}
871
Richard Uhler9b994ea2015-06-24 08:44:19 -0700872// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
873// OAT file. Expect: The status is kNoDexOptNeeded.
874TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
875 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
876
877 Copy(GetStrippedDexSrc1(), dex_location);
878
879 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700880 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700881
Andreas Gampe29d38e72016-03-23 15:31:51 +0000882 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
883 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
884 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100885 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000886 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100887 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700888
889 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000890 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
891 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700892 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
893
894 // Make the oat file up to date. This should have no effect.
895 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700896 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700897 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -0700898 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -0700899 error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700900
Andreas Gampe29d38e72016-03-23 15:31:51 +0000901 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
902 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700903
904 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000905 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
906 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700907 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
908}
909
Richard Uhler66d874d2015-01-15 09:37:19 -0800910// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
911// OAT files both have patch delta of 0.
Richard Uhler5923b522016-12-08 09:48:01 +0000912// Expect: It shouldn't crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800913TEST_F(OatFileAssistantTest, OdexOatOverlap) {
914 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700915 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800916
Calin Juravle357c66d2017-05-04 01:57:17 +0000917 // Create the dex, the odex and the oat files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800918 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000919 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Calin Juravle357c66d2017-05-04 01:57:17 +0000920 GenerateOatForTest(dex_location.c_str(),
921 CompilerFilter::kSpeed,
922 /*relocate*/false,
923 /*pic*/false,
924 /*with_alternate_image*/false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800925
926 // Verify things don't go bad.
Calin Juravle357c66d2017-05-04 01:57:17 +0000927 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800928
Calin Juravle357c66d2017-05-04 01:57:17 +0000929 // -kDex2OatForRelocation is expected rather than kDex2OatForRelocation
930 // based on the assumption that the odex location is more up-to-date than the oat
Richard Uhler70a84262016-11-08 16:51:51 +0000931 // location, even if they both need relocation.
Calin Juravle357c66d2017-05-04 01:57:17 +0000932 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000933 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800934
935 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000936 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
937 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700938 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800939
940 // Things aren't relocated, so it should fall back to interpreted.
941 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
942 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700943
Richard Uhler66d874d2015-01-15 09:37:19 -0800944 EXPECT_FALSE(oat_file->IsExecutable());
945 std::vector<std::unique_ptr<const DexFile>> dex_files;
946 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
947 EXPECT_EQ(1u, dex_files.size());
948}
949
Andreas Gampe29d38e72016-03-23 15:31:51 +0000950// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
951// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
952TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
953 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
954 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000955
956 // Create the dex and odex files
957 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100958 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000959
960 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700961 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000962
Andreas Gampe29d38e72016-03-23 15:31:51 +0000963 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +0100964 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000965 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000966 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000967
968 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000969 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000970 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000971 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
972}
973
Richard Uhler66d874d2015-01-15 09:37:19 -0800974// Case: We have a DEX file and up-to-date OAT file for it.
975// Expect: We should load an executable dex file.
976TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +0000977 if (IsExecutedAsRoot()) {
978 // We cannot simulate non writable locations when executed as root: b/38000545.
979 LOG(ERROR) << "Test skipped because it's running as root";
980 return;
981 }
982
Richard Uhler66d874d2015-01-15 09:37:19 -0800983 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
984
985 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000986 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800987
Calin Juravle357c66d2017-05-04 01:57:17 +0000988 ScopedNonWritable scoped_non_writable(dex_location);
989 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
990
Richard Uhler66d874d2015-01-15 09:37:19 -0800991 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700992 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000993
994 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
995 ASSERT_TRUE(oat_file.get() != nullptr);
996 EXPECT_TRUE(oat_file->IsExecutable());
997 std::vector<std::unique_ptr<const DexFile>> dex_files;
998 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
999 EXPECT_EQ(1u, dex_files.size());
1000}
1001
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001002// Case: We have a DEX file and up-to-date quicken OAT file for it.
Andreas Gampe29d38e72016-03-23 15:31:51 +00001003// Expect: We should still load the oat file as executable.
1004TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001005 if (IsExecutedAsRoot()) {
1006 // We cannot simulate non writable locations when executed as root: b/38000545.
1007 LOG(ERROR) << "Test skipped because it's running as root";
1008 return;
1009 }
1010
Andreas Gampe29d38e72016-03-23 15:31:51 +00001011 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
1012
1013 Copy(GetDexSrc1(), dex_location);
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001014 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001015
Calin Juravle357c66d2017-05-04 01:57:17 +00001016 ScopedNonWritable scoped_non_writable(dex_location);
1017 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1018
Andreas Gampe29d38e72016-03-23 15:31:51 +00001019 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001020 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001021
1022 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1023 ASSERT_TRUE(oat_file.get() != nullptr);
1024 EXPECT_TRUE(oat_file->IsExecutable());
1025 std::vector<std::unique_ptr<const DexFile>> dex_files;
1026 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1027 EXPECT_EQ(1u, dex_files.size());
1028}
1029
1030// Case: We have a DEX file and up-to-date OAT file for it.
1031// Expect: Loading non-executable should load the oat non-executable.
1032TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001033 if (IsExecutedAsRoot()) {
1034 // We cannot simulate non writable locations when executed as root: b/38000545.
1035 LOG(ERROR) << "Test skipped because it's running as root";
1036 return;
1037 }
1038
Richard Uhler66d874d2015-01-15 09:37:19 -08001039 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
1040
1041 Copy(GetDexSrc1(), dex_location);
Calin Juravle357c66d2017-05-04 01:57:17 +00001042
1043 ScopedNonWritable scoped_non_writable(dex_location);
1044 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1045
Andreas Gampe29d38e72016-03-23 15:31:51 +00001046 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001047
1048 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001049 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001050
1051 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1052 ASSERT_TRUE(oat_file.get() != nullptr);
1053 EXPECT_FALSE(oat_file->IsExecutable());
1054 std::vector<std::unique_ptr<const DexFile>> dex_files;
1055 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1056 EXPECT_EQ(1u, dex_files.size());
1057}
1058
Richard Uhler8327cf72015-10-13 16:34:59 -07001059// Case: We don't have a DEX file and can't write the oat file.
1060// Expect: We should fail to generate the oat file without crashing.
1061TEST_F(OatFileAssistantTest, GenNoDex) {
Calin Juravle357c66d2017-05-04 01:57:17 +00001062 if (IsExecutedAsRoot()) {
1063 // We cannot simulate non writable locations when executed as root: b/38000545.
1064 LOG(ERROR) << "Test skipped because it's running as root";
1065 return;
1066 }
Richard Uhler8327cf72015-10-13 16:34:59 -07001067
Calin Juravle357c66d2017-05-04 01:57:17 +00001068 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
1069
1070 ScopedNonWritable scoped_non_writable(dex_location);
1071 ASSERT_TRUE(scoped_non_writable.IsSuccessful());
1072
1073 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -07001074 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001075 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Calin Juravle357c66d2017-05-04 01:57:17 +00001076 // We should get kUpdateSucceeded from MakeUpToDate since there's nothing
1077 // that can be done in this situation.
1078 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001079 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Calin Juravle357c66d2017-05-04 01:57:17 +00001080
1081 // Verify it didn't create an oat in the default location (dalvik-cache).
1082 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
1083 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus());
1084 // Verify it didn't create the odex file in the default location (../oat/isa/...odex)
1085 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OdexFileStatus());
Richard Uhler8327cf72015-10-13 16:34:59 -07001086}
1087
Richard Uhler66d874d2015-01-15 09:37:19 -08001088// Turn an absolute path into a path relative to the current working
1089// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -08001090static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001091 char buf[MAXPATHLEN];
1092 std::string cwd = getcwd(buf, MAXPATHLEN);
1093
1094 // Split the target and cwd paths into components.
1095 std::vector<std::string> target_path;
1096 std::vector<std::string> cwd_path;
1097 Split(target, '/', &target_path);
1098 Split(cwd, '/', &cwd_path);
1099
1100 // Reverse the path components, so we can use pop_back().
1101 std::reverse(target_path.begin(), target_path.end());
1102 std::reverse(cwd_path.begin(), cwd_path.end());
1103
1104 // Drop the common prefix of the paths. Because we reversed the path
1105 // components, this becomes the common suffix of target_path and cwd_path.
1106 while (!target_path.empty() && !cwd_path.empty()
1107 && target_path.back() == cwd_path.back()) {
1108 target_path.pop_back();
1109 cwd_path.pop_back();
1110 }
1111
1112 // For each element of the remaining cwd_path, add '..' to the beginning
1113 // of the target path. Because we reversed the path components, we add to
1114 // the end of target_path.
1115 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1116 target_path.push_back("..");
1117 }
1118
1119 // Reverse again to get the right path order, and join to get the result.
1120 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001121 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001122}
1123
1124// Case: Non-absolute path to Dex location.
1125// Expect: Not sure, but it shouldn't crash.
1126TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1127 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1128 Copy(GetDexSrc1(), abs_dex_location);
1129
1130 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -07001131 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001132
1133 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001134 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001135 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001136 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1137 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001138}
1139
1140// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001141// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001142TEST_F(OatFileAssistantTest, ShortDexLocation) {
1143 std::string dex_location = "/xx";
1144
Richard Uhlerd1472a22016-04-15 15:18:56 -07001145 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001146
1147 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001148 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1149 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001150 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1151 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001152 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001153
Richard Uhler9b994ea2015-06-24 08:44:19 -07001154 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -08001155 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001156 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -07001157 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001158 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -07001159 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -08001160}
1161
1162// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001163// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001164TEST_F(OatFileAssistantTest, LongDexExtension) {
1165 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1166 Copy(GetDexSrc1(), dex_location);
1167
Richard Uhlerd1472a22016-04-15 15:18:56 -07001168 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001169
Richard Uhler7225a8d2016-11-22 10:12:03 +00001170 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001171 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001172
1173 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001174 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1175 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001176}
1177
1178// A task to generate a dex location. Used by the RaceToGenerate test.
1179class RaceGenerateTask : public Task {
1180 public:
1181 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
Jeff Haof0192c82016-03-28 20:39:50 -07001182 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001183 {}
1184
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01001185 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001186 // Load the dex files, and save a pointer to the loaded oat file, so that
1187 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001188 std::vector<std::unique_ptr<const DexFile>> dex_files;
1189 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001190 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001191 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1192 dex_location_.c_str(),
Jeff Hao0cb17282017-07-12 14:51:49 -07001193 Runtime::Current()->GetSystemClassLoader(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001194 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001195 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001196 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001197 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -07001198 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
1199 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001200 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001201 }
1202
1203 const OatFile* GetLoadedOatFile() const {
1204 return loaded_oat_file_;
1205 }
1206
1207 private:
1208 std::string dex_location_;
1209 std::string oat_location_;
1210 const OatFile* loaded_oat_file_;
1211};
1212
1213// Test the case where multiple processes race to generate an oat file.
1214// This simulates multiple processes using multiple threads.
1215//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001216// We want unique Oat files to be loaded even when there is a race to load.
1217// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1218// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001219TEST_F(OatFileAssistantTest, RaceToGenerate) {
1220 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001221 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001222
Jeff Hao0cb17282017-07-12 14:51:49 -07001223 // Start the runtime to initialize the system's class loader.
1224 Thread::Current()->TransitionFromSuspendedToRunnable();
1225 runtime_->Start();
1226
Richard Uhler66d874d2015-01-15 09:37:19 -08001227 // We use the lib core dex file, because it's large, and hopefully should
1228 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001229 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001230
1231 const int kNumThreads = 32;
1232 Thread* self = Thread::Current();
1233 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1234 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1235 for (int i = 0; i < kNumThreads; i++) {
1236 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1237 thread_pool.AddTask(self, task.get());
1238 tasks.push_back(std::move(task));
1239 }
1240 thread_pool.StartWorkers(self);
1241 thread_pool.Wait(self, true, false);
1242
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001243 // Verify every task got a unique oat file.
1244 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001245 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001246 const OatFile* oat_file = task->GetLoadedOatFile();
1247 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1248 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001249 }
1250}
1251
1252// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1253// disabled.
1254// Expect: We should load the odex file non-executable.
1255TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1256 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001257 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001258
1259 // Create the dex and odex files
1260 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001261 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001262
1263 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001264 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001265
1266 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1267 ASSERT_TRUE(oat_file.get() != nullptr);
1268 EXPECT_FALSE(oat_file->IsExecutable());
1269 std::vector<std::unique_ptr<const DexFile>> dex_files;
1270 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1271 EXPECT_EQ(1u, dex_files.size());
1272}
1273
1274// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1275// disabled.
1276// Expect: We should load the odex file non-executable.
1277TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1278 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001279 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001280
1281 // Create the dex and odex files
1282 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001283 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001284
1285 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001286 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001287
1288 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1289 ASSERT_TRUE(oat_file.get() != nullptr);
1290 EXPECT_FALSE(oat_file->IsExecutable());
1291 std::vector<std::unique_ptr<const DexFile>> dex_files;
1292 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1293 EXPECT_EQ(2u, dex_files.size());
1294}
1295
Richard Uhlerf4b34872016-04-13 11:03:46 -07001296TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
1297 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
1298 Copy(GetDexSrc1(), dex_location);
1299
Richard Uhlerd1472a22016-04-15 15:18:56 -07001300 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhlerf4b34872016-04-13 11:03:46 -07001301
1302 std::string error_msg;
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001303 Runtime::Current()->AddCompilerOption("--compiler-filter=quicken");
Richard Uhlerf4b34872016-04-13 11:03:46 -07001304 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001305 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001306 error_msg;
Calin Juravle357c66d2017-05-04 01:57:17 +00001307 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001308 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Calin Juravle357c66d2017-05-04 01:57:17 +00001309 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Richard Uhlerf4b34872016-04-13 11:03:46 -07001310 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1311
1312 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
1313 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;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001316 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Nicolas Geoffray49cda062017-04-21 13:08:25 +01001317 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001318 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1319 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1320
1321 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
1322 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001323 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001324}
1325
Richard Uhlerb81881d2016-04-19 13:08:04 -07001326TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001327 std::string error_msg;
1328 std::string odex_file;
1329
Richard Uhlerb81881d2016-04-19 13:08:04 -07001330 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001331 "/foo/bar/baz.jar", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001332 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001333
Richard Uhlerb81881d2016-04-19 13:08:04 -07001334 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001335 "/foo/bar/baz.funnyext", InstructionSet::kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001336 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001337
Richard Uhlerb81881d2016-04-19 13:08:04 -07001338 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001339 "nopath.jar", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001340 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Vladimir Marko33bff252017-11-01 14:35:42 +00001341 "/foo/bar/baz_noext", InstructionSet::kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001342}
1343
Richard Uhler23cedd22015-04-08 13:17:29 -07001344// Verify the dexopt status values from dalvik.system.DexFile
1345// match the OatFileAssistant::DexOptStatus values.
1346TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001347 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1348 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1349 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1350 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1351 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
1352 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001353 };
1354
Richard Uhler23cedd22015-04-08 13:17:29 -07001355 ScopedObjectAccess soa(Thread::Current());
1356 StackHandleScope<1> hs(soa.Self());
1357 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1358 Handle<mirror::Class> dexfile(
1359 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
Andreas Gampefa4333d2017-02-14 11:10:34 -08001360 ASSERT_FALSE(dexfile == nullptr);
Richard Uhler23cedd22015-04-08 13:17:29 -07001361 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1362
Richard Uhler7225a8d2016-11-22 10:12:03 +00001363 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1364 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001365 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001366 ASSERT_FALSE(art_field == nullptr);
1367 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1368 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1369 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001370}
Richard Uhler66d874d2015-01-15 09:37:19 -08001371
Calin Juravle07c6d722017-06-07 17:06:12 +00001372// Verify that when no compiler filter is passed the default one from OatFileAssistant is used.
1373TEST_F(OatFileAssistantTest, DefaultMakeUpToDateFilter) {
1374 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1375 Copy(GetDexSrc1(), dex_location);
1376
1377 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1378
1379 const CompilerFilter::Filter default_filter =
1380 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1381 std::string error_msg;
1382 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001383 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) <<
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001384 error_msg;
Calin Juravle07c6d722017-06-07 17:06:12 +00001385 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1386 oat_file_assistant.GetDexOptNeeded(default_filter));
1387 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1388 EXPECT_NE(nullptr, oat_file.get());
1389 EXPECT_EQ(default_filter, oat_file->GetCompilerFilter());
1390}
1391
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001392TEST_F(OatFileAssistantTest, MakeUpToDateWithSpecialSharedLibrary) {
1393 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1394 Copy(GetDexSrc1(), dex_location);
1395
1396 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1397
1398 const CompilerFilter::Filter default_filter =
1399 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1400 std::string error_msg;
Calin Juravle44e5efa2017-09-12 00:54:26 -07001401 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001402 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1403 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1404 oat_file_assistant.GetDexOptNeeded(default_filter));
1405 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1406 EXPECT_NE(nullptr, oat_file.get());
1407 EXPECT_EQ(kSpecialSharedLibrary,
1408 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1409}
1410
1411TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) {
1412 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1413 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1414 Copy(GetDexSrc1(), dex_location);
1415 Copy(GetDexSrc2(), context_location);
1416
1417 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1418
1419 const CompilerFilter::Filter default_filter =
1420 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1421 std::string error_msg;
1422 std::string context_str = "PCL[" + context_location + "]";
Calin Juravle44e5efa2017-09-12 00:54:26 -07001423 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1424 ASSERT_TRUE(context != nullptr);
1425 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1426
1427 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001428 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1429 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Calin Juravle44e5efa2017-09-12 00:54:26 -07001430 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1431
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001432 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1433 EXPECT_NE(nullptr, oat_file.get());
Calin Juravle27e0d1f2017-07-26 00:16:07 -07001434 EXPECT_EQ(context->EncodeContextForOatFile(""),
1435 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey));
1436}
1437
Calin Juravle44e5efa2017-09-12 00:54:26 -07001438TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) {
1439 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1440 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1441 Copy(GetDexSrc1(), dex_location);
1442 Copy(GetDexSrc2(), context_location);
1443
1444 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1445
1446 const CompilerFilter::Filter default_filter =
1447 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1448 std::string error_msg;
1449 std::string context_str = "PCL[" + context_location + "]";
1450 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1451 ASSERT_TRUE(context != nullptr);
1452 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1453
1454 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1455 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1456 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1457 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get()));
1458
1459 // Update the context by overriding the jar file.
1460 Copy(GetMultiDexSrc2(), context_location);
1461 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str);
1462 ASSERT_TRUE(updated_context != nullptr);
1463 // DexOptNeeded should advise compilation from scratch.
1464 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
1465 oat_file_assistant.GetDexOptNeeded(
1466 default_filter, false, false, updated_context.get()));
1467}
1468
Calin Juravle20c46442017-09-12 00:54:26 -07001469TEST_F(OatFileAssistantTest, GetDexOptNeededWithUpToDateContextRelative) {
1470 std::string dex_location = GetScratchDir() + "/TestDex.jar";
1471 std::string context_location = GetScratchDir() + "/ContextDex.jar";
1472 Copy(GetDexSrc1(), dex_location);
1473 Copy(GetDexSrc2(), context_location);
1474
1475 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1476
1477 const CompilerFilter::Filter default_filter =
1478 OatFileAssistant::kDefaultCompilerFilterForDexLoading;
1479 std::string error_msg;
1480 std::string context_str = "PCL[" + context_location + "]";
1481 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str);
1482 ASSERT_TRUE(context != nullptr);
1483 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, ""));
1484
1485 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg);
1486 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg;
1487
1488 // A relative context simulates a dependent split context.
1489 std::unique_ptr<ClassLoaderContext> relative_context =
1490 ClassLoaderContext::Create("PCL[ContextDex.jar]");
1491 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
1492 oat_file_assistant.GetDexOptNeeded(
1493 default_filter, false, false, relative_context.get()));
1494}
1495
Richard Uhler66d874d2015-01-15 09:37:19 -08001496// TODO: More Tests:
1497// * Test class linker falls back to unquickened dex for DexNoOat
1498// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001499// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001500// * Test for status of oat while oat is being generated (how?)
1501// * Test case where 32 and 64 bit boot class paths differ,
1502// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1503// 64 bit boot class paths.
1504// * Test unexpected scenarios (?):
1505// - Dex is stripped, don't have odex.
1506// - Oat file corrupted after status check, before reload unexecutable
1507// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001508} // namespace art