blob: 4541468cb34fe188d12530720b488b429d46a742 [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
17#include "oat_file_assistant.h"
18
19#include <algorithm>
20#include <fstream>
21#include <string>
22#include <vector>
23#include <sys/param.h>
24
25#include <backtrace/BacktraceMap.h>
26#include <gtest/gtest.h>
27
Mathieu Chartierc7853442015-03-27 14:35:38 -070028#include "art_field-inl.h"
Vladimir Marko3481ba22015-04-13 12:22:36 +010029#include "class_linker-inl.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080030#include "common_runtime_test.h"
Andreas Gampebb9c6b12015-03-29 13:56:36 -070031#include "compiler_callbacks.h"
Richard Uhlerf16d5722015-05-11 09:32:47 -070032#include "gc/space/image_space.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080033#include "mem_map.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070034#include "oat_file_manager.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080035#include "os.h"
Richard Uhler23cedd22015-04-08 13:17:29 -070036#include "scoped_thread_state_change.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080037#include "thread-inl.h"
38#include "utils.h"
39
40namespace art {
41
42class OatFileAssistantTest : public CommonRuntimeTest {
43 public:
44 virtual void SetUp() {
45 ReserveImageSpace();
46 CommonRuntimeTest::SetUp();
47
48 // Create a scratch directory to work from.
49 scratch_dir_ = android_data_ + "/OatFileAssistantTest";
50 ASSERT_EQ(0, mkdir(scratch_dir_.c_str(), 0700));
51
Richard Uhler63434112015-03-16 14:32:16 -070052 // Create a subdirectory in scratch for odex files.
53 odex_oat_dir_ = scratch_dir_ + "/oat";
54 ASSERT_EQ(0, mkdir(odex_oat_dir_.c_str(), 0700));
55
56 odex_dir_ = odex_oat_dir_ + "/" + std::string(GetInstructionSetString(kRuntimeISA));
57 ASSERT_EQ(0, mkdir(odex_dir_.c_str(), 0700));
58
Richard Uhler66d874d2015-01-15 09:37:19 -080059
60 // Verify the environment is as we expect
61 uint32_t checksum;
62 std::string error_msg;
63 ASSERT_TRUE(OS::FileExists(GetImageFile().c_str()))
64 << "Expected pre-compiled boot image to be at: " << GetImageFile();
65 ASSERT_TRUE(OS::FileExists(GetDexSrc1().c_str()))
66 << "Expected dex file to be at: " << GetDexSrc1();
67 ASSERT_TRUE(OS::FileExists(GetStrippedDexSrc1().c_str()))
68 << "Expected stripped dex file to be at: " << GetStrippedDexSrc1();
Igor Murashkinb1d8c312015-08-04 11:18:43 -070069 ASSERT_FALSE(DexFile::GetChecksum(GetStrippedDexSrc1().c_str(), &checksum, &error_msg))
Richard Uhler66d874d2015-01-15 09:37:19 -080070 << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1();
Richard Uhler66d874d2015-01-15 09:37:19 -080071 ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
72 << "Expected dex file to be at: " << GetDexSrc2();
Richard Uhler67ff7d12015-05-14 13:21:13 -070073
74 // GetMultiDexSrc2 should have the same primary dex checksum as
75 // GetMultiDexSrc1, but a different secondary dex checksum.
76 std::vector<std::unique_ptr<const DexFile>> multi1;
77 ASSERT_TRUE(DexFile::Open(GetMultiDexSrc1().c_str(),
Igor Murashkinb1d8c312015-08-04 11:18:43 -070078 GetMultiDexSrc1().c_str(), &error_msg, &multi1)) << error_msg;
Richard Uhler67ff7d12015-05-14 13:21:13 -070079 ASSERT_GT(multi1.size(), 1u);
80
81 std::vector<std::unique_ptr<const DexFile>> multi2;
82 ASSERT_TRUE(DexFile::Open(GetMultiDexSrc2().c_str(),
Igor Murashkinb1d8c312015-08-04 11:18:43 -070083 GetMultiDexSrc2().c_str(), &error_msg, &multi2)) << error_msg;
Richard Uhler67ff7d12015-05-14 13:21:13 -070084 ASSERT_GT(multi2.size(), 1u);
85
86 ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum());
87 ASSERT_NE(multi1[1]->GetLocationChecksum(), multi2[1]->GetLocationChecksum());
Richard Uhler66d874d2015-01-15 09:37:19 -080088 }
89
90 virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
Richard Uhler892fc962015-03-10 16:57:05 +000091 // options->push_back(std::make_pair("-verbose:oat", nullptr));
Richard Uhler66d874d2015-01-15 09:37:19 -080092
93 // Set up the image location.
94 options->push_back(std::make_pair("-Ximage:" + GetImageLocation(),
95 nullptr));
96 // Make sure compilercallbacks are not set so that relocation will be
97 // enabled.
Andreas Gampebb9c6b12015-03-29 13:56:36 -070098 callbacks_.reset();
Richard Uhler66d874d2015-01-15 09:37:19 -080099 }
100
101 virtual void PreRuntimeCreate() {
102 UnreserveImageSpace();
103 }
104
105 virtual void PostRuntimeCreate() {
106 ReserveImageSpace();
107 }
108
109 virtual void TearDown() {
Richard Uhler63434112015-03-16 14:32:16 -0700110 ClearDirectory(odex_dir_.c_str());
111 ASSERT_EQ(0, rmdir(odex_dir_.c_str()));
112
113 ClearDirectory(odex_oat_dir_.c_str());
114 ASSERT_EQ(0, rmdir(odex_oat_dir_.c_str()));
Richard Uhler66d874d2015-01-15 09:37:19 -0800115
116 ClearDirectory(scratch_dir_.c_str());
117 ASSERT_EQ(0, rmdir(scratch_dir_.c_str()));
118
119 CommonRuntimeTest::TearDown();
120 }
121
122 void Copy(std::string src, std::string dst) {
123 std::ifstream src_stream(src, std::ios::binary);
124 std::ofstream dst_stream(dst, std::ios::binary);
125
126 dst_stream << src_stream.rdbuf();
127 }
128
129 // Returns the directory where the pre-compiled core.art can be found.
130 // TODO: We should factor out this into common tests somewhere rather than
131 // re-hardcoding it here (This was copied originally from the elf writer
132 // test).
133 std::string GetImageDirectory() {
134 if (IsHost()) {
135 const char* host_dir = getenv("ANDROID_HOST_OUT");
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700136 CHECK(host_dir != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800137 return std::string(host_dir) + "/framework";
138 } else {
139 return std::string("/data/art-test");
140 }
141 }
142
143 std::string GetImageLocation() {
144 return GetImageDirectory() + "/core.art";
145 }
146
147 std::string GetImageFile() {
148 return GetImageDirectory() + "/" + GetInstructionSetString(kRuntimeISA)
149 + "/core.art";
150 }
151
152 std::string GetDexSrc1() {
153 return GetTestDexFileName("Main");
154 }
155
156 // Returns the path to a dex file equivalent to GetDexSrc1, but with the dex
157 // file stripped.
158 std::string GetStrippedDexSrc1() {
159 return GetTestDexFileName("MainStripped");
160 }
161
162 std::string GetMultiDexSrc1() {
163 return GetTestDexFileName("MultiDex");
164 }
165
Richard Uhler67ff7d12015-05-14 13:21:13 -0700166 // Returns the path to a multidex file equivalent to GetMultiDexSrc2, but
167 // with the contents of the secondary dex file changed.
168 std::string GetMultiDexSrc2() {
169 return GetTestDexFileName("MultiDexModifiedSecondary");
170 }
171
Richard Uhler66d874d2015-01-15 09:37:19 -0800172 std::string GetDexSrc2() {
173 return GetTestDexFileName("Nested");
174 }
175
176 // Scratch directory, for dex and odex files (oat files will go in the
177 // dalvik cache).
178 std::string GetScratchDir() {
179 return scratch_dir_;
180 }
181
Richard Uhler63434112015-03-16 14:32:16 -0700182 // Odex directory is the subdirectory in the scratch directory where odex
Richard Uhler66d874d2015-01-15 09:37:19 -0800183 // files should be located.
Richard Uhler63434112015-03-16 14:32:16 -0700184 std::string GetOdexDir() {
185 return odex_dir_;
Richard Uhler66d874d2015-01-15 09:37:19 -0800186 }
187
Richard Uhler93aa2102015-08-10 14:47:41 -0700188 // Generate a non-PIC odex file for the purposes of test.
Richard Uhler94f5bda2015-07-22 08:25:11 -0700189 // The generated odex file will be un-relocated.
Richard Uhler66d874d2015-01-15 09:37:19 -0800190 void GenerateOdexForTest(const std::string& dex_location,
Richard Uhler93aa2102015-08-10 14:47:41 -0700191 const std::string& odex_location) {
192 // To generate an un-relocated odex file, we first compile a relocated
193 // version of the file, then manually call patchoat to make it look as if
194 // it is unrelocated.
195 std::string relocated_odex_location = odex_location + ".relocated";
196 std::vector<std::string> args;
197 args.push_back("--dex-file=" + dex_location);
198 args.push_back("--oat-file=" + relocated_odex_location);
199 args.push_back("--include-patch-information");
200
201 // We need to use the quick compiler to generate non-PIC code, because
202 // the optimizing compiler always generates PIC.
203 args.push_back("--compiler-backend=Quick");
204
205 std::string error_msg;
206 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
207
208 // Use patchoat to unrelocate the relocated odex file.
209 Runtime* runtime = Runtime::Current();
210 std::vector<std::string> argv;
211 argv.push_back(runtime->GetPatchoatExecutable());
212 argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(kRuntimeISA)));
213 argv.push_back("--input-oat-file=" + relocated_odex_location);
214 argv.push_back("--output-oat-file=" + odex_location);
215 argv.push_back("--base-offset-delta=0x00008000");
216 std::string command_line(Join(argv, ' '));
217 ASSERT_TRUE(Exec(argv, &error_msg)) << error_msg;
218
219 // Verify the odex file was generated as expected and really is
220 // unrelocated.
221 std::unique_ptr<OatFile> odex_file(OatFile::Open(
222 odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
223 false, dex_location.c_str(), &error_msg));
224 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
225
Jeff Haodcdc85b2015-12-04 14:06:18 -0800226 const std::vector<gc::space::ImageSpace*> image_spaces =
227 runtime->GetHeap()->GetBootImageSpaces();
228 ASSERT_TRUE(!image_spaces.empty() && image_spaces[0] != nullptr);
229 const ImageHeader& image_header = image_spaces[0]->GetImageHeader();
Richard Uhler93aa2102015-08-10 14:47:41 -0700230 const OatHeader& oat_header = odex_file->GetOatHeader();
231 EXPECT_FALSE(odex_file->IsPic());
232 EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum());
233 EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()),
234 oat_header.GetImageFileLocationOatDataBegin());
235 EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta());
236 }
237
238 void GeneratePicOdexForTest(const std::string& dex_location,
239 const std::string& odex_location) {
240 // Temporarily redirect the dalvik cache so dex2oat doesn't find the
241 // relocated image file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800242 std::string android_data_tmp = GetScratchDir() + "AndroidDataTmp";
243 setenv("ANDROID_DATA", android_data_tmp.c_str(), 1);
244 std::vector<std::string> args;
245 args.push_back("--dex-file=" + dex_location);
246 args.push_back("--oat-file=" + odex_location);
Richard Uhler93aa2102015-08-10 14:47:41 -0700247 args.push_back("--compile-pic");
Richard Uhler66d874d2015-01-15 09:37:19 -0800248 args.push_back("--runtime-arg");
249 args.push_back("-Xnorelocate");
250 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700251 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800252 setenv("ANDROID_DATA", android_data_.c_str(), 1);
Richard Uhler94f5bda2015-07-22 08:25:11 -0700253
254 // Verify the odex file was generated as expected.
255 std::unique_ptr<OatFile> odex_file(OatFile::Open(
256 odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700257 false, dex_location.c_str(), &error_msg));
Richard Uhler94f5bda2015-07-22 08:25:11 -0700258 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
Richard Uhler93aa2102015-08-10 14:47:41 -0700259 EXPECT_TRUE(odex_file->IsPic());
Richard Uhler66d874d2015-01-15 09:37:19 -0800260 }
261
David Brazdilce4b0ba2016-01-28 15:05:49 +0000262 void GenerateExtractOnlyOdexForTest(const std::string& dex_location,
Calin Juravled91b8a22016-02-18 18:47:37 +0000263 const std::string& odex_location) {
David Brazdilce4b0ba2016-01-28 15:05:49 +0000264 std::vector<std::string> args;
265 args.push_back("--dex-file=" + dex_location);
266 args.push_back("--oat-file=" + odex_location);
267 args.push_back("--compiler-filter=verify-at-runtime");
268 std::string error_msg;
269 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
270
271 // Verify the odex file was generated as expected.
272 std::unique_ptr<OatFile> odex_file(OatFile::Open(
273 odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
274 false, dex_location.c_str(), &error_msg));
275 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
276 EXPECT_TRUE(odex_file->IsExtractOnly());
277 EXPECT_EQ(odex_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0u);
278 EXPECT_EQ(odex_file->GetOatHeader().GetImageFileLocationOatDataBegin(), 0u);
279 EXPECT_EQ(odex_file->GetOatHeader().GetImagePatchDelta(), 0);
Calin Juravled91b8a22016-02-18 18:47:37 +0000280 }
281
282 void GenerateProfileGuideOdexForTest(const std::string& dex_location,
283 const std::string& odex_location) {
284 std::vector<std::string> args;
285 args.push_back("--dex-file=" + dex_location);
286 args.push_back("--oat-file=" + odex_location);
287 ScratchFile profile_file;
288 args.push_back("--profile-file=" + profile_file.GetFilename());
289 std::string error_msg;
290 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
291
292 // Verify the odex file was generated as expected.
293 std::unique_ptr<OatFile> odex_file(OatFile::Open(
294 odex_location.c_str(), odex_location.c_str(), nullptr, nullptr,
295 false, dex_location.c_str(), &error_msg));
296 printf("error %s", error_msg.c_str());
297 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
298 EXPECT_TRUE(odex_file->IsProfileGuideCompiled());
299 }
David Brazdilce4b0ba2016-01-28 15:05:49 +0000300
Richard Uhler66d874d2015-01-15 09:37:19 -0800301 private:
302 // Reserve memory around where the image will be loaded so other memory
303 // won't conflict when it comes time to load the image.
304 // This can be called with an already loaded image to reserve the space
305 // around it.
306 void ReserveImageSpace() {
307 MemMap::Init();
308
309 // Ensure a chunk of memory is reserved for the image space.
310 uintptr_t reservation_start = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MIN_DELTA;
311 uintptr_t reservation_end = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MAX_DELTA
Hiroshi Yamauchi3dbf2342015-03-17 16:01:11 -0700312 // Include the main space that has to come right after the
313 // image in case of the GSS collector.
314 + 384 * MB;
Richard Uhler66d874d2015-01-15 09:37:19 -0800315
Richard Uhler66d874d2015-01-15 09:37:19 -0800316 std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true));
317 ASSERT_TRUE(map.get() != nullptr) << "Failed to build process map";
318 for (BacktraceMap::const_iterator it = map->begin();
319 reservation_start < reservation_end && it != map->end(); ++it) {
Richard Uhler3efe9792015-03-30 16:18:03 -0700320 ReserveImageSpaceChunk(reservation_start, std::min(it->start, reservation_end));
321 reservation_start = std::max(reservation_start, it->end);
322 }
323 ReserveImageSpaceChunk(reservation_start, reservation_end);
324 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800325
Richard Uhler3efe9792015-03-30 16:18:03 -0700326 // Reserve a chunk of memory for the image space in the given range.
327 // Only has effect for chunks with a positive number of bytes.
328 void ReserveImageSpaceChunk(uintptr_t start, uintptr_t end) {
329 if (start < end) {
330 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800331 image_reservation_.push_back(std::unique_ptr<MemMap>(
332 MemMap::MapAnonymous("image reservation",
Richard Uhler3efe9792015-03-30 16:18:03 -0700333 reinterpret_cast<uint8_t*>(start), end - start,
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700334 PROT_NONE, false, false, &error_msg)));
Richard Uhler66d874d2015-01-15 09:37:19 -0800335 ASSERT_TRUE(image_reservation_.back().get() != nullptr) << error_msg;
336 LOG(INFO) << "Reserved space for image " <<
337 reinterpret_cast<void*>(image_reservation_.back()->Begin()) << "-" <<
338 reinterpret_cast<void*>(image_reservation_.back()->End());
Richard Uhler66d874d2015-01-15 09:37:19 -0800339 }
340 }
341
342
343 // Unreserve any memory reserved by ReserveImageSpace. This should be called
344 // before the image is loaded.
345 void UnreserveImageSpace() {
346 image_reservation_.clear();
347 }
348
349 std::string scratch_dir_;
Richard Uhler63434112015-03-16 14:32:16 -0700350 std::string odex_oat_dir_;
351 std::string odex_dir_;
Richard Uhler66d874d2015-01-15 09:37:19 -0800352 std::vector<std::unique_ptr<MemMap>> image_reservation_;
353};
354
355class OatFileAssistantNoDex2OatTest : public OatFileAssistantTest {
356 public:
357 virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
358 OatFileAssistantTest::SetUpRuntimeOptions(options);
359 options->push_back(std::make_pair("-Xnodex2oat", nullptr));
360 }
361};
362
363// Generate an oat file for the purposes of test, as opposed to testing
364// generation of oat files.
365static void GenerateOatForTest(const char* dex_location) {
Calin Juravled91b8a22016-02-18 18:47:37 +0000366 OatFileAssistant oat_file_assistant(dex_location,
367 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800368
369 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700370 ASSERT_TRUE(oat_file_assistant.GenerateOatFile(&error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800371}
372
373// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700374// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800375TEST_F(OatFileAssistantTest, DexNoOat) {
376 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
377 Copy(GetDexSrc1(), dex_location);
378
Calin Juravled91b8a22016-02-18 18:47:37 +0000379 OatFileAssistant oat_file_assistant(dex_location.c_str(),
380 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800381
Richard Uhler95abd042015-03-24 09:51:28 -0700382 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800383
384 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
385 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
386 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
387 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
388 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
Richard Uhler95abd042015-03-24 09:51:28 -0700389 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OdexFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800390 EXPECT_FALSE(oat_file_assistant.OatFileExists());
391 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
392 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
393 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler95abd042015-03-24 09:51:28 -0700394 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, 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
398// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700399// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800400TEST_F(OatFileAssistantTest, NoDexNoOat) {
401 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
402
Calin Juravled91b8a22016-02-18 18:47:37 +0000403 OatFileAssistant oat_file_assistant(dex_location.c_str(),
404 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800405
Richard Uhler9b994ea2015-06-24 08:44:19 -0700406 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
407 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
408
409 // Trying to make the oat file up to date should not fail or crash.
410 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700411 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700412
413 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800414 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
415 EXPECT_EQ(nullptr, oat_file.get());
416}
417
418// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700419// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800420TEST_F(OatFileAssistantTest, OatUpToDate) {
421 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
422 Copy(GetDexSrc1(), dex_location);
423 GenerateOatForTest(dex_location.c_str());
424
Calin Juravled91b8a22016-02-18 18:47:37 +0000425 OatFileAssistant oat_file_assistant(dex_location.c_str(),
426 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800427
Richard Uhler95abd042015-03-24 09:51:28 -0700428 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800429 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
430 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
431 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
432 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
433 EXPECT_TRUE(oat_file_assistant.OatFileExists());
434 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
435 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
436 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler95abd042015-03-24 09:51:28 -0700437 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700438 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800439}
440
441// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700442// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800443TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
444 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
445 Copy(GetMultiDexSrc1(), dex_location);
446 GenerateOatForTest(dex_location.c_str());
447
Calin Juravled91b8a22016-02-18 18:47:37 +0000448 OatFileAssistant oat_file_assistant(dex_location.c_str(),
449 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler95abd042015-03-24 09:51:28 -0700450 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700451 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700452
453 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700454 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800455 ASSERT_TRUE(oat_file.get() != nullptr);
456 EXPECT_TRUE(oat_file->IsExecutable());
457 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700458 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
459 EXPECT_EQ(2u, dex_files.size());
460}
461
Richard Uhler67ff7d12015-05-14 13:21:13 -0700462// Case: We have a MultiDEX file where the secondary dex file is out of date.
463// Expect: The status is kDex2OatNeeded.
464TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) {
465 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
466
467 // Compile code for GetMultiDexSrc1.
468 Copy(GetMultiDexSrc1(), dex_location);
469 GenerateOatForTest(dex_location.c_str());
470
471 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
472 // is out of date.
473 Copy(GetMultiDexSrc2(), dex_location);
474
Calin Juravled91b8a22016-02-18 18:47:37 +0000475 OatFileAssistant oat_file_assistant(dex_location.c_str(),
476 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700477 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700478 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700479}
480
Richard Uhlere5fed032015-03-18 08:21:11 -0700481// Case: We have a MultiDEX file and up-to-date OAT file for it with relative
482// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700483// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700484TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
485 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700486 std::string oat_location = GetOdexDir() + "/RelativeEncodedDexLocation.oat";
Richard Uhlere5fed032015-03-18 08:21:11 -0700487
488 // Create the dex file
489 Copy(GetMultiDexSrc1(), dex_location);
490
491 // Create the oat file with relative encoded dex location.
492 std::vector<std::string> args;
493 args.push_back("--dex-file=" + dex_location);
494 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
495 args.push_back("--oat-file=" + oat_location);
496
497 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700498 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700499
500 // Verify we can load both dex files.
501 OatFileAssistant oat_file_assistant(dex_location.c_str(),
502 oat_location.c_str(),
Calin Juravled91b8a22016-02-18 18:47:37 +0000503 OatFileAssistant::kFullCompilation,
Richard Uhlere5fed032015-03-18 08:21:11 -0700504 kRuntimeISA, true);
505 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
506 ASSERT_TRUE(oat_file.get() != nullptr);
507 EXPECT_TRUE(oat_file->IsExecutable());
508 std::vector<std::unique_ptr<const DexFile>> dex_files;
509 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800510 EXPECT_EQ(2u, dex_files.size());
511}
512
Richard Uhler95abd042015-03-24 09:51:28 -0700513// Case: We have a DEX file and out-of-date OAT file.
514// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800515TEST_F(OatFileAssistantTest, OatOutOfDate) {
516 std::string dex_location = GetScratchDir() + "/OatOutOfDate.jar";
517
518 // We create a dex, generate an oat for it, then overwrite the dex with a
519 // different dex to make the oat out of date.
520 Copy(GetDexSrc1(), dex_location);
521 GenerateOatForTest(dex_location.c_str());
522 Copy(GetDexSrc2(), dex_location);
523
Calin Juravled91b8a22016-02-18 18:47:37 +0000524 OatFileAssistant oat_file_assistant(dex_location.c_str(),
525 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler95abd042015-03-24 09:51:28 -0700526 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800527
528 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
529 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
530 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
531 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
532 EXPECT_TRUE(oat_file_assistant.OatFileExists());
533 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
534 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700535 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800536}
537
538// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700539// Expect: The status is kPatchOatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800540TEST_F(OatFileAssistantTest, DexOdexNoOat) {
541 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700542 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800543
544 // Create the dex and odex files
545 Copy(GetDexSrc1(), dex_location);
546 GenerateOdexForTest(dex_location, odex_location);
547
548 // Verify the status.
Calin Juravled91b8a22016-02-18 18:47:37 +0000549 OatFileAssistant oat_file_assistant(dex_location.c_str(),
550 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800551
Richard Uhler95abd042015-03-24 09:51:28 -0700552 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800553
554 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
555 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
556 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
557 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
558 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
Richard Uhler66d874d2015-01-15 09:37:19 -0800559 EXPECT_FALSE(oat_file_assistant.OatFileExists());
560 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
561 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700562 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700563
564 // We should still be able to get the non-executable odex file to run from.
565 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
566 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800567}
568
569// Case: We have a stripped DEX file and an ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700570// Expect: The status is kPatchOatNeeded
Richard Uhler66d874d2015-01-15 09:37:19 -0800571TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
572 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700573 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800574
575 // Create the dex and odex files
576 Copy(GetDexSrc1(), dex_location);
577 GenerateOdexForTest(dex_location, odex_location);
578
579 // Strip the dex file
580 Copy(GetStrippedDexSrc1(), dex_location);
581
582 // Verify the status.
Calin Juravled91b8a22016-02-18 18:47:37 +0000583 OatFileAssistant oat_file_assistant(dex_location.c_str(),
584 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800585
Richard Uhler95abd042015-03-24 09:51:28 -0700586 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800587
588 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
589 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
590 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
591 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
592 EXPECT_FALSE(oat_file_assistant.OatFileExists());
593 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
594 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700595 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800596
597 // Make the oat file up to date.
598 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700599 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800600
Richard Uhler95abd042015-03-24 09:51:28 -0700601 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800602
603 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
604 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
605 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
606 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
607 EXPECT_TRUE(oat_file_assistant.OatFileExists());
608 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
609 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700610 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800611
612 // Verify we can load the dex files from it.
613 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
614 ASSERT_TRUE(oat_file.get() != nullptr);
615 EXPECT_TRUE(oat_file->IsExecutable());
616 std::vector<std::unique_ptr<const DexFile>> dex_files;
617 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
618 EXPECT_EQ(1u, dex_files.size());
619}
620
Richard Uhler95abd042015-03-24 09:51:28 -0700621// Case: We have a stripped DEX file, an ODEX file, and an out-of-date OAT file.
622// Expect: The status is kPatchOatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800623TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
624 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700625 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800626
627 // Create the oat file from a different dex file so it looks out of date.
628 Copy(GetDexSrc2(), dex_location);
629 GenerateOatForTest(dex_location.c_str());
630
631 // Create the odex file
632 Copy(GetDexSrc1(), dex_location);
633 GenerateOdexForTest(dex_location, odex_location);
634
635 // Strip the dex file.
636 Copy(GetStrippedDexSrc1(), dex_location);
637
638 // Verify the status.
Calin Juravled91b8a22016-02-18 18:47:37 +0000639 OatFileAssistant oat_file_assistant(dex_location.c_str(),
640 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800641
Richard Uhler95abd042015-03-24 09:51:28 -0700642 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800643
644 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
645 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
646 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
647 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
648 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
649 EXPECT_TRUE(oat_file_assistant.OatFileExists());
650 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
651 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700652 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800653
654 // Make the oat file up to date.
655 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700656 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800657
Richard Uhler95abd042015-03-24 09:51:28 -0700658 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800659
660 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
661 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
662 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
663 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
664 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
665 EXPECT_TRUE(oat_file_assistant.OatFileExists());
666 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
667 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
668 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700669 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800670
671 // Verify we can load the dex files from it.
672 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
673 ASSERT_TRUE(oat_file.get() != nullptr);
674 EXPECT_TRUE(oat_file->IsExecutable());
675 std::vector<std::unique_ptr<const DexFile>> dex_files;
676 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
677 EXPECT_EQ(1u, dex_files.size());
678}
679
Richard Uhler9b994ea2015-06-24 08:44:19 -0700680// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
681// OAT file. Expect: The status is kNoDexOptNeeded.
682TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
683 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
684
685 Copy(GetStrippedDexSrc1(), dex_location);
686
687 // Verify the status.
Calin Juravled91b8a22016-02-18 18:47:37 +0000688 OatFileAssistant oat_file_assistant(dex_location.c_str(),
689 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700690
691 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
692
693 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
694 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
695 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
696 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
697 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
698 EXPECT_FALSE(oat_file_assistant.OatFileExists());
699 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
700 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
701 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
702
703 // Make the oat file up to date. This should have no effect.
704 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700705 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700706
707 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
708
709 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
710 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
711 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
712 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
713 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
714 EXPECT_FALSE(oat_file_assistant.OatFileExists());
715 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
716 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
717 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
718}
719
Richard Uhler95abd042015-03-24 09:51:28 -0700720// Case: We have a DEX file, no ODEX file and an OAT file that needs
721// relocation.
722// Expect: The status is kSelfPatchOatNeeded.
723TEST_F(OatFileAssistantTest, SelfRelocation) {
724 std::string dex_location = GetScratchDir() + "/SelfRelocation.jar";
725 std::string oat_location = GetOdexDir() + "/SelfRelocation.oat";
726
727 // Create the dex and odex files
728 Copy(GetDexSrc1(), dex_location);
729 GenerateOdexForTest(dex_location, oat_location);
730
731 OatFileAssistant oat_file_assistant(dex_location.c_str(),
Calin Juravled91b8a22016-02-18 18:47:37 +0000732 oat_location.c_str(), OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler95abd042015-03-24 09:51:28 -0700733
734 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
735
736 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
737 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
738 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
739 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
740 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
741 EXPECT_TRUE(oat_file_assistant.OatFileExists());
742 EXPECT_TRUE(oat_file_assistant.OatFileNeedsRelocation());
743 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
744 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700745 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700746
747 // Make the oat file up to date.
748 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700749 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler95abd042015-03-24 09:51:28 -0700750
751 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
752
753 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
754 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
755 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
756 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
757 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
758 EXPECT_TRUE(oat_file_assistant.OatFileExists());
759 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
760 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
761 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700762 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700763
764 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
765 ASSERT_TRUE(oat_file.get() != nullptr);
766 EXPECT_TRUE(oat_file->IsExecutable());
767 std::vector<std::unique_ptr<const DexFile>> dex_files;
768 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
769 EXPECT_EQ(1u, dex_files.size());
770}
771
Richard Uhler66d874d2015-01-15 09:37:19 -0800772// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
773// OAT files both have patch delta of 0.
Richard Uhler95abd042015-03-24 09:51:28 -0700774// Expect: It shouldn't crash, and status is kPatchOatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800775TEST_F(OatFileAssistantTest, OdexOatOverlap) {
776 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700777 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
778 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -0800779
780 // Create the dex and odex files
781 Copy(GetDexSrc1(), dex_location);
782 GenerateOdexForTest(dex_location, odex_location);
783
784 // Create the oat file by copying the odex so they are located in the same
785 // place in memory.
786 Copy(odex_location, oat_location);
787
788 // Verify things don't go bad.
789 OatFileAssistant oat_file_assistant(dex_location.c_str(),
Calin Juravled91b8a22016-02-18 18:47:37 +0000790 oat_location.c_str(), OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800791
Richard Uhler95abd042015-03-24 09:51:28 -0700792 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800793
794 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
795 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
796 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
797 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
798 EXPECT_TRUE(oat_file_assistant.OatFileExists());
799 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
800 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700801 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800802
803 // Things aren't relocated, so it should fall back to interpreted.
804 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
805 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700806
Richard Uhler66d874d2015-01-15 09:37:19 -0800807 EXPECT_FALSE(oat_file->IsExecutable());
808 std::vector<std::unique_ptr<const DexFile>> dex_files;
809 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
810 EXPECT_EQ(1u, dex_files.size());
811}
812
813// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700814// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
Richard Uhler66d874d2015-01-15 09:37:19 -0800815TEST_F(OatFileAssistantTest, DexPicOdexNoOat) {
816 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700817 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800818
819 // Create the dex and odex files
820 Copy(GetDexSrc1(), dex_location);
821 GeneratePicOdexForTest(dex_location, odex_location);
822
823 // Verify the status.
Calin Juravled91b8a22016-02-18 18:47:37 +0000824 OatFileAssistant oat_file_assistant(dex_location.c_str(),
825 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800826
Richard Uhler95abd042015-03-24 09:51:28 -0700827 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800828
829 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
830 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
831 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
832 EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate());
833 EXPECT_FALSE(oat_file_assistant.OatFileExists());
834 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
835 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700836 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800837}
838
David Brazdilce4b0ba2016-01-28 15:05:49 +0000839// Case: We have a DEX file and a ExtractOnly ODEX file, but no OAT file.
840// Expect: The status is kNoDexOptNeeded, because ExtractOnly contains no code.
841TEST_F(OatFileAssistantTest, DexExtractOnlyOdexNoOat) {
842 std::string dex_location = GetScratchDir() + "/DexExtractOnlyOdexNoOat.jar";
843 std::string odex_location = GetOdexDir() + "/DexExtractOnlyOdexNoOat.odex";
844
845 // Create the dex and odex files
846 Copy(GetDexSrc1(), dex_location);
847 GenerateExtractOnlyOdexForTest(dex_location, odex_location);
848
849 // Verify the status.
Calin Juravled91b8a22016-02-18 18:47:37 +0000850 OatFileAssistant oat_file_assistant(dex_location.c_str(),
851 OatFileAssistant::kFullCompilation | OatFileAssistant::kExtractOnly,
852 kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000853
854 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
855
856 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
857 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
858 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
859 EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate());
860 EXPECT_FALSE(oat_file_assistant.OatFileExists());
861 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
862 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
863 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
864}
865
Richard Uhler66d874d2015-01-15 09:37:19 -0800866// Case: We have a DEX file and up-to-date OAT file for it.
867// Expect: We should load an executable dex file.
868TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
869 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
870
871 Copy(GetDexSrc1(), dex_location);
872 GenerateOatForTest(dex_location.c_str());
873
874 // Load the oat using an oat file assistant.
Calin Juravled91b8a22016-02-18 18:47:37 +0000875 OatFileAssistant oat_file_assistant(dex_location.c_str(),
876 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800877
878 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
879 ASSERT_TRUE(oat_file.get() != nullptr);
880 EXPECT_TRUE(oat_file->IsExecutable());
881 std::vector<std::unique_ptr<const DexFile>> dex_files;
882 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
883 EXPECT_EQ(1u, dex_files.size());
884}
885
886// Case: We have a DEX file and up-to-date OAT file for it.
887// Expect: Loading non-executable should load the oat non-executable.
888TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
889 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
890
891 Copy(GetDexSrc1(), dex_location);
892 GenerateOatForTest(dex_location.c_str());
893
894 // Load the oat using an oat file assistant.
Calin Juravled91b8a22016-02-18 18:47:37 +0000895 OatFileAssistant oat_file_assistant(dex_location.c_str(),
896 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800897
898 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
899 ASSERT_TRUE(oat_file.get() != nullptr);
900 EXPECT_FALSE(oat_file->IsExecutable());
901 std::vector<std::unique_ptr<const DexFile>> dex_files;
902 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
903 EXPECT_EQ(1u, dex_files.size());
904}
905
906// Case: We have a DEX file.
907// Expect: We should load an executable dex file from an alternative oat
908// location.
909TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) {
910 std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar";
911 std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat";
912
913 Copy(GetDexSrc1(), dex_location);
914
915 OatFileAssistant oat_file_assistant(
Calin Juravled91b8a22016-02-18 18:47:37 +0000916 dex_location.c_str(), oat_location.c_str(),
917 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800918 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700919 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800920
921 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
922 ASSERT_TRUE(oat_file.get() != nullptr);
923 EXPECT_TRUE(oat_file->IsExecutable());
924 std::vector<std::unique_ptr<const DexFile>> dex_files;
925 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
926 EXPECT_EQ(1u, dex_files.size());
927
928 EXPECT_TRUE(OS::FileExists(oat_location.c_str()));
929
930 // Verify it didn't create an oat in the default location.
Calin Juravled91b8a22016-02-18 18:47:37 +0000931 OatFileAssistant ofm(dex_location.c_str(),
932 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800933 EXPECT_FALSE(ofm.OatFileExists());
934}
935
Richard Uhler8327cf72015-10-13 16:34:59 -0700936// Case: We have a DEX file but can't write the oat file.
937// Expect: We should fail to make the oat file up to date.
938TEST_F(OatFileAssistantTest, LoadDexUnwriteableAlternateOat) {
939 std::string dex_location = GetScratchDir() + "/LoadDexUnwriteableAlternateOat.jar";
940
941 // Make the oat location unwritable by inserting some non-existent
942 // intermediate directories.
943 std::string oat_location = GetScratchDir() + "/foo/bar/LoadDexUnwriteableAlternateOat.oat";
944
945 Copy(GetDexSrc1(), dex_location);
946
947 OatFileAssistant oat_file_assistant(
Calin Juravled91b8a22016-02-18 18:47:37 +0000948 dex_location.c_str(), oat_location.c_str(),
949 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -0700950 std::string error_msg;
951 ASSERT_FALSE(oat_file_assistant.MakeUpToDate(&error_msg));
952
953 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
954 ASSERT_TRUE(oat_file.get() == nullptr);
955}
956
957// Case: We don't have a DEX file and can't write the oat file.
958// Expect: We should fail to generate the oat file without crashing.
959TEST_F(OatFileAssistantTest, GenNoDex) {
960 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
961 std::string oat_location = GetScratchDir() + "/GenNoDex.oat";
962
963 OatFileAssistant oat_file_assistant(
Calin Juravled91b8a22016-02-18 18:47:37 +0000964 dex_location.c_str(), oat_location.c_str(),
965 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -0700966 std::string error_msg;
967 ASSERT_FALSE(oat_file_assistant.GenerateOatFile(&error_msg));
968}
969
Richard Uhler66d874d2015-01-15 09:37:19 -0800970// Turn an absolute path into a path relative to the current working
971// directory.
972static std::string MakePathRelative(std::string target) {
973 char buf[MAXPATHLEN];
974 std::string cwd = getcwd(buf, MAXPATHLEN);
975
976 // Split the target and cwd paths into components.
977 std::vector<std::string> target_path;
978 std::vector<std::string> cwd_path;
979 Split(target, '/', &target_path);
980 Split(cwd, '/', &cwd_path);
981
982 // Reverse the path components, so we can use pop_back().
983 std::reverse(target_path.begin(), target_path.end());
984 std::reverse(cwd_path.begin(), cwd_path.end());
985
986 // Drop the common prefix of the paths. Because we reversed the path
987 // components, this becomes the common suffix of target_path and cwd_path.
988 while (!target_path.empty() && !cwd_path.empty()
989 && target_path.back() == cwd_path.back()) {
990 target_path.pop_back();
991 cwd_path.pop_back();
992 }
993
994 // For each element of the remaining cwd_path, add '..' to the beginning
995 // of the target path. Because we reversed the path components, we add to
996 // the end of target_path.
997 for (unsigned int i = 0; i < cwd_path.size(); i++) {
998 target_path.push_back("..");
999 }
1000
1001 // Reverse again to get the right path order, and join to get the result.
1002 std::reverse(target_path.begin(), target_path.end());
1003 return Join(target_path, '/');
1004}
1005
1006// Case: Non-absolute path to Dex location.
1007// Expect: Not sure, but it shouldn't crash.
1008TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1009 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1010 Copy(GetDexSrc1(), abs_dex_location);
1011
1012 std::string dex_location = MakePathRelative(abs_dex_location);
Calin Juravled91b8a22016-02-18 18:47:37 +00001013 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1014 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001015
1016 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler95abd042015-03-24 09:51:28 -07001017 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -08001018 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
1019 EXPECT_FALSE(oat_file_assistant.OatFileExists());
1020 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
1021 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
1022 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
1023 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
1024}
1025
1026// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001027// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001028TEST_F(OatFileAssistantTest, ShortDexLocation) {
1029 std::string dex_location = "/xx";
1030
Calin Juravled91b8a22016-02-18 18:47:37 +00001031 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1032 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001033
1034 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001035 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -08001036 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
1037 EXPECT_FALSE(oat_file_assistant.OatFileExists());
1038 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
1039 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
1040 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
1041 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001042 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001043
Richard Uhler9b994ea2015-06-24 08:44:19 -07001044 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -08001045 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001046 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -07001047 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -08001048}
1049
1050// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001051// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001052TEST_F(OatFileAssistantTest, LongDexExtension) {
1053 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1054 Copy(GetDexSrc1(), dex_location);
1055
Calin Juravled91b8a22016-02-18 18:47:37 +00001056 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1057 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001058
Richard Uhler95abd042015-03-24 09:51:28 -07001059 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -08001060
1061 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
1062 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
1063 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
1064 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
1065 EXPECT_FALSE(oat_file_assistant.OatFileExists());
1066 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
1067 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
1068}
1069
1070// A task to generate a dex location. Used by the RaceToGenerate test.
1071class RaceGenerateTask : public Task {
1072 public:
1073 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
1074 : dex_location_(dex_location), oat_location_(oat_location),
1075 loaded_oat_file_(nullptr)
1076 {}
1077
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01001078 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001079 // Load the dex files, and save a pointer to the loaded oat file, so that
1080 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001081 std::vector<std::unique_ptr<const DexFile>> dex_files;
1082 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001083 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001084 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1085 dex_location_.c_str(),
1086 oat_location_.c_str(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001087 /*class_loader*/nullptr,
1088 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001089 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001090 &error_msgs);
Richard Uhler66d874d2015-01-15 09:37:19 -08001091 CHECK(!dex_files.empty()) << Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -07001092 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
1093 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001094 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001095 }
1096
1097 const OatFile* GetLoadedOatFile() const {
1098 return loaded_oat_file_;
1099 }
1100
1101 private:
1102 std::string dex_location_;
1103 std::string oat_location_;
1104 const OatFile* loaded_oat_file_;
1105};
1106
1107// Test the case where multiple processes race to generate an oat file.
1108// This simulates multiple processes using multiple threads.
1109//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001110// We want unique Oat files to be loaded even when there is a race to load.
1111// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1112// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001113TEST_F(OatFileAssistantTest, RaceToGenerate) {
1114 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001115 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001116
1117 // We use the lib core dex file, because it's large, and hopefully should
1118 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001119 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001120
1121 const int kNumThreads = 32;
1122 Thread* self = Thread::Current();
1123 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1124 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1125 for (int i = 0; i < kNumThreads; i++) {
1126 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1127 thread_pool.AddTask(self, task.get());
1128 tasks.push_back(std::move(task));
1129 }
1130 thread_pool.StartWorkers(self);
1131 thread_pool.Wait(self, true, false);
1132
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001133 // Verify every task got a unique oat file.
1134 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001135 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001136 const OatFile* oat_file = task->GetLoadedOatFile();
1137 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1138 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001139 }
1140}
1141
1142// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1143// disabled.
1144// Expect: We should load the odex file non-executable.
1145TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1146 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001147 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001148
1149 // Create the dex and odex files
1150 Copy(GetDexSrc1(), dex_location);
1151 GenerateOdexForTest(dex_location, odex_location);
1152
1153 // Load the oat using an executable oat file assistant.
Calin Juravled91b8a22016-02-18 18:47:37 +00001154 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1155 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001156
1157 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1158 ASSERT_TRUE(oat_file.get() != nullptr);
1159 EXPECT_FALSE(oat_file->IsExecutable());
1160 std::vector<std::unique_ptr<const DexFile>> dex_files;
1161 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1162 EXPECT_EQ(1u, dex_files.size());
1163}
1164
1165// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1166// disabled.
1167// Expect: We should load the odex file non-executable.
1168TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1169 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001170 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001171
1172 // Create the dex and odex files
1173 Copy(GetMultiDexSrc1(), dex_location);
1174 GenerateOdexForTest(dex_location, odex_location);
1175
1176 // Load the oat using an executable oat file assistant.
Calin Juravled91b8a22016-02-18 18:47:37 +00001177 OatFileAssistant oat_file_assistant(dex_location.c_str(),
1178 OatFileAssistant::kFullCompilation, kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001179
1180 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1181 ASSERT_TRUE(oat_file.get() != nullptr);
1182 EXPECT_FALSE(oat_file->IsExecutable());
1183 std::vector<std::unique_ptr<const DexFile>> dex_files;
1184 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1185 EXPECT_EQ(2u, dex_files.size());
1186}
1187
1188TEST(OatFileAssistantUtilsTest, DexFilenameToOdexFilename) {
1189 std::string error_msg;
1190 std::string odex_file;
1191
1192 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001193 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001194 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001195
1196 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001197 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001198 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001199
1200 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001201 "nopath.jar", kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001202 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001203 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001204}
1205
Calin Juravled91b8a22016-02-18 18:47:37 +00001206// Case: We have a DEX file, extract-only ODEX, and fully compiled OAT.
1207// Expect: The status depends on the target compilation type mask.
1208TEST_F(OatFileAssistantTest, TargetCompilationType) {
1209 std::string dex_location = GetScratchDir() + "/TargetCompilationType.jar";
1210 std::string odex_location = GetOdexDir() + "/TargetCompilationType.odex";
1211 Copy(GetDexSrc1(), dex_location);
1212 GenerateExtractOnlyOdexForTest(dex_location, odex_location);
1213 GenerateOatForTest(dex_location.c_str());
1214
1215 OatFileAssistant ofa_full(dex_location.c_str(),
1216 OatFileAssistant::kFullCompilation, kRuntimeISA, false);
1217 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, ofa_full.GetDexOptNeeded());
1218 EXPECT_FALSE(ofa_full.IsInBootClassPath());
1219 EXPECT_TRUE(ofa_full.OdexFileIsOutOfDate());
1220 EXPECT_TRUE(ofa_full.OatFileIsUpToDate());
1221
1222 OatFileAssistant ofa_extract(dex_location.c_str(),
1223 OatFileAssistant::kExtractOnly, kRuntimeISA, false);
1224 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, ofa_extract.GetDexOptNeeded());
1225 EXPECT_FALSE(ofa_extract.IsInBootClassPath());
1226 EXPECT_TRUE(ofa_extract.OdexFileIsUpToDate());
1227 EXPECT_TRUE(ofa_extract.OatFileIsOutOfDate());
1228
1229 OatFileAssistant ofa_profile(dex_location.c_str(),
1230 OatFileAssistant::kProfileGuideCompilation, kRuntimeISA, false);
1231 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, ofa_profile.GetDexOptNeeded());
1232 EXPECT_FALSE(ofa_profile.IsInBootClassPath());
1233 EXPECT_TRUE(ofa_profile.OdexFileIsOutOfDate());
1234 EXPECT_TRUE(ofa_profile.OatFileIsOutOfDate());
1235
1236 OatFileAssistant ofa_extract_full(dex_location.c_str(),
1237 OatFileAssistant::kFullCompilation | OatFileAssistant::kExtractOnly,
1238 kRuntimeISA, false);
1239 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, ofa_extract_full.GetDexOptNeeded());
1240 EXPECT_FALSE(ofa_extract_full.IsInBootClassPath());
1241 EXPECT_TRUE(ofa_extract_full.OdexFileIsUpToDate());
1242 EXPECT_TRUE(ofa_extract_full.OatFileIsUpToDate());
1243}
1244
Richard Uhler23cedd22015-04-08 13:17:29 -07001245// Verify the dexopt status values from dalvik.system.DexFile
1246// match the OatFileAssistant::DexOptStatus values.
1247TEST_F(OatFileAssistantTest, DexOptStatusValues) {
1248 ScopedObjectAccess soa(Thread::Current());
1249 StackHandleScope<1> hs(soa.Self());
1250 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1251 Handle<mirror::Class> dexfile(
1252 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
1253 ASSERT_FALSE(dexfile.Get() == nullptr);
1254 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1255
Mathieu Chartierc7853442015-03-27 14:35:38 -07001256 ArtField* no_dexopt_needed = mirror::Class::FindStaticField(
Richard Uhler23cedd22015-04-08 13:17:29 -07001257 soa.Self(), dexfile, "NO_DEXOPT_NEEDED", "I");
1258 ASSERT_FALSE(no_dexopt_needed == nullptr);
1259 EXPECT_EQ(no_dexopt_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1260 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, no_dexopt_needed->GetInt(dexfile.Get()));
1261
Mathieu Chartierc7853442015-03-27 14:35:38 -07001262 ArtField* dex2oat_needed = mirror::Class::FindStaticField(
Richard Uhler23cedd22015-04-08 13:17:29 -07001263 soa.Self(), dexfile, "DEX2OAT_NEEDED", "I");
1264 ASSERT_FALSE(dex2oat_needed == nullptr);
1265 EXPECT_EQ(dex2oat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1266 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, dex2oat_needed->GetInt(dexfile.Get()));
1267
Mathieu Chartierc7853442015-03-27 14:35:38 -07001268 ArtField* patchoat_needed = mirror::Class::FindStaticField(
Richard Uhler23cedd22015-04-08 13:17:29 -07001269 soa.Self(), dexfile, "PATCHOAT_NEEDED", "I");
1270 ASSERT_FALSE(patchoat_needed == nullptr);
1271 EXPECT_EQ(patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1272 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, patchoat_needed->GetInt(dexfile.Get()));
1273
Mathieu Chartierc7853442015-03-27 14:35:38 -07001274 ArtField* self_patchoat_needed = mirror::Class::FindStaticField(
Richard Uhler23cedd22015-04-08 13:17:29 -07001275 soa.Self(), dexfile, "SELF_PATCHOAT_NEEDED", "I");
1276 ASSERT_FALSE(self_patchoat_needed == nullptr);
1277 EXPECT_EQ(self_patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1278 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, self_patchoat_needed->GetInt(dexfile.Get()));
Calin Juravled91b8a22016-02-18 18:47:37 +00001279
1280 ArtField* compilation_type_full = mirror::Class::FindStaticField(
1281 soa.Self(), dexfile, "COMPILATION_TYPE_FULL", "I");
1282 ASSERT_FALSE(compilation_type_full == nullptr);
1283 EXPECT_EQ(compilation_type_full->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1284 EXPECT_EQ(OatFileAssistant::kFullCompilation, compilation_type_full->GetInt(dexfile.Get()));
1285
1286 ArtField* compilation_type_profile_guide = mirror::Class::FindStaticField(
1287 soa.Self(), dexfile, "COMPILATION_TYPE_PROFILE_GUIDE", "I");
1288 ASSERT_FALSE(compilation_type_profile_guide == nullptr);
1289 EXPECT_EQ(compilation_type_profile_guide->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1290 EXPECT_EQ(OatFileAssistant::kProfileGuideCompilation,
1291 compilation_type_profile_guide->GetInt(dexfile.Get()));
1292
1293 ArtField* compilation_type_extract_only = mirror::Class::FindStaticField(
1294 soa.Self(), dexfile, "COMPILATION_TYPE_EXTRACT_ONLY", "I");
1295 ASSERT_FALSE(compilation_type_extract_only == nullptr);
1296 EXPECT_EQ(compilation_type_extract_only->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1297 EXPECT_EQ(OatFileAssistant::kExtractOnly, compilation_type_extract_only->GetInt(dexfile.Get()));
Richard Uhler23cedd22015-04-08 13:17:29 -07001298}
Richard Uhler66d874d2015-01-15 09:37:19 -08001299
1300// TODO: More Tests:
1301// * Test class linker falls back to unquickened dex for DexNoOat
1302// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001303// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001304// * Test for status of oat while oat is being generated (how?)
1305// * Test case where 32 and 64 bit boot class paths differ,
1306// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1307// 64 bit boot class paths.
1308// * Test unexpected scenarios (?):
1309// - Dex is stripped, don't have odex.
1310// - Oat file corrupted after status check, before reload unexecutable
1311// because it's unrelocated and no dex2oat
Calin Juravled91b8a22016-02-18 18:47:37 +00001312// * Test unrelocated specific target compilation type can be relocated to
1313// make it up to date.
Richard Uhler66d874d2015-01-15 09:37:19 -08001314
1315} // namespace art