blob: 83d4457a1c5b369baaef38714db8eb7f2fe0ef45 [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,
263 const std::string& odex_location) {
264 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);
280}
281
Richard Uhler66d874d2015-01-15 09:37:19 -0800282 private:
283 // Reserve memory around where the image will be loaded so other memory
284 // won't conflict when it comes time to load the image.
285 // This can be called with an already loaded image to reserve the space
286 // around it.
287 void ReserveImageSpace() {
288 MemMap::Init();
289
290 // Ensure a chunk of memory is reserved for the image space.
291 uintptr_t reservation_start = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MIN_DELTA;
292 uintptr_t reservation_end = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MAX_DELTA
Hiroshi Yamauchi3dbf2342015-03-17 16:01:11 -0700293 // Include the main space that has to come right after the
294 // image in case of the GSS collector.
295 + 384 * MB;
Richard Uhler66d874d2015-01-15 09:37:19 -0800296
Richard Uhler66d874d2015-01-15 09:37:19 -0800297 std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true));
298 ASSERT_TRUE(map.get() != nullptr) << "Failed to build process map";
299 for (BacktraceMap::const_iterator it = map->begin();
300 reservation_start < reservation_end && it != map->end(); ++it) {
Richard Uhler3efe9792015-03-30 16:18:03 -0700301 ReserveImageSpaceChunk(reservation_start, std::min(it->start, reservation_end));
302 reservation_start = std::max(reservation_start, it->end);
303 }
304 ReserveImageSpaceChunk(reservation_start, reservation_end);
305 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800306
Richard Uhler3efe9792015-03-30 16:18:03 -0700307 // Reserve a chunk of memory for the image space in the given range.
308 // Only has effect for chunks with a positive number of bytes.
309 void ReserveImageSpaceChunk(uintptr_t start, uintptr_t end) {
310 if (start < end) {
311 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800312 image_reservation_.push_back(std::unique_ptr<MemMap>(
313 MemMap::MapAnonymous("image reservation",
Richard Uhler3efe9792015-03-30 16:18:03 -0700314 reinterpret_cast<uint8_t*>(start), end - start,
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700315 PROT_NONE, false, false, &error_msg)));
Richard Uhler66d874d2015-01-15 09:37:19 -0800316 ASSERT_TRUE(image_reservation_.back().get() != nullptr) << error_msg;
317 LOG(INFO) << "Reserved space for image " <<
318 reinterpret_cast<void*>(image_reservation_.back()->Begin()) << "-" <<
319 reinterpret_cast<void*>(image_reservation_.back()->End());
Richard Uhler66d874d2015-01-15 09:37:19 -0800320 }
321 }
322
323
324 // Unreserve any memory reserved by ReserveImageSpace. This should be called
325 // before the image is loaded.
326 void UnreserveImageSpace() {
327 image_reservation_.clear();
328 }
329
330 std::string scratch_dir_;
Richard Uhler63434112015-03-16 14:32:16 -0700331 std::string odex_oat_dir_;
332 std::string odex_dir_;
Richard Uhler66d874d2015-01-15 09:37:19 -0800333 std::vector<std::unique_ptr<MemMap>> image_reservation_;
334};
335
336class OatFileAssistantNoDex2OatTest : public OatFileAssistantTest {
337 public:
338 virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
339 OatFileAssistantTest::SetUpRuntimeOptions(options);
340 options->push_back(std::make_pair("-Xnodex2oat", nullptr));
341 }
342};
343
344// Generate an oat file for the purposes of test, as opposed to testing
345// generation of oat files.
346static void GenerateOatForTest(const char* dex_location) {
347 OatFileAssistant oat_file_assistant(dex_location, kRuntimeISA, false);
348
349 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700350 ASSERT_TRUE(oat_file_assistant.GenerateOatFile(&error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800351}
352
353// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700354// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800355TEST_F(OatFileAssistantTest, DexNoOat) {
356 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
357 Copy(GetDexSrc1(), dex_location);
358
359 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
360
Richard Uhler95abd042015-03-24 09:51:28 -0700361 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800362
363 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
364 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
365 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
366 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
367 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
Richard Uhler95abd042015-03-24 09:51:28 -0700368 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OdexFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800369 EXPECT_FALSE(oat_file_assistant.OatFileExists());
370 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
371 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
372 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler95abd042015-03-24 09:51:28 -0700373 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700374 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800375}
376
377// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700378// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800379TEST_F(OatFileAssistantTest, NoDexNoOat) {
380 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
381
382 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
383
Richard Uhler9b994ea2015-06-24 08:44:19 -0700384 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
385 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
386
387 // Trying to make the oat file up to date should not fail or crash.
388 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700389 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700390
391 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800392 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
393 EXPECT_EQ(nullptr, oat_file.get());
394}
395
396// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700397// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800398TEST_F(OatFileAssistantTest, OatUpToDate) {
399 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
400 Copy(GetDexSrc1(), dex_location);
401 GenerateOatForTest(dex_location.c_str());
402
403 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
404
Richard Uhler95abd042015-03-24 09:51:28 -0700405 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800406 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
407 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
408 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
409 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
410 EXPECT_TRUE(oat_file_assistant.OatFileExists());
411 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
412 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
413 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler95abd042015-03-24 09:51:28 -0700414 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700415 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800416}
417
418// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700419// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800420TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
421 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
422 Copy(GetMultiDexSrc1(), dex_location);
423 GenerateOatForTest(dex_location.c_str());
424
Richard Uhlere5fed032015-03-18 08:21:11 -0700425 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler95abd042015-03-24 09:51:28 -0700426 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700427 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700428
429 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700430 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800431 ASSERT_TRUE(oat_file.get() != nullptr);
432 EXPECT_TRUE(oat_file->IsExecutable());
433 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700434 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
435 EXPECT_EQ(2u, dex_files.size());
436}
437
Richard Uhler67ff7d12015-05-14 13:21:13 -0700438// Case: We have a MultiDEX file where the secondary dex file is out of date.
439// Expect: The status is kDex2OatNeeded.
440TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) {
441 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
442
443 // Compile code for GetMultiDexSrc1.
444 Copy(GetMultiDexSrc1(), dex_location);
445 GenerateOatForTest(dex_location.c_str());
446
447 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
448 // is out of date.
449 Copy(GetMultiDexSrc2(), dex_location);
450
451 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
452 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700453 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700454}
455
Richard Uhlere5fed032015-03-18 08:21:11 -0700456// Case: We have a MultiDEX file and up-to-date OAT file for it with relative
457// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700458// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700459TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
460 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700461 std::string oat_location = GetOdexDir() + "/RelativeEncodedDexLocation.oat";
Richard Uhlere5fed032015-03-18 08:21:11 -0700462
463 // Create the dex file
464 Copy(GetMultiDexSrc1(), dex_location);
465
466 // Create the oat file with relative encoded dex location.
467 std::vector<std::string> args;
468 args.push_back("--dex-file=" + dex_location);
469 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
470 args.push_back("--oat-file=" + oat_location);
471
472 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700473 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700474
475 // Verify we can load both dex files.
476 OatFileAssistant oat_file_assistant(dex_location.c_str(),
477 oat_location.c_str(),
478 kRuntimeISA, true);
479 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
480 ASSERT_TRUE(oat_file.get() != nullptr);
481 EXPECT_TRUE(oat_file->IsExecutable());
482 std::vector<std::unique_ptr<const DexFile>> dex_files;
483 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800484 EXPECT_EQ(2u, dex_files.size());
485}
486
Richard Uhler95abd042015-03-24 09:51:28 -0700487// Case: We have a DEX file and out-of-date OAT file.
488// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800489TEST_F(OatFileAssistantTest, OatOutOfDate) {
490 std::string dex_location = GetScratchDir() + "/OatOutOfDate.jar";
491
492 // We create a dex, generate an oat for it, then overwrite the dex with a
493 // different dex to make the oat out of date.
494 Copy(GetDexSrc1(), dex_location);
495 GenerateOatForTest(dex_location.c_str());
496 Copy(GetDexSrc2(), dex_location);
497
498 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler95abd042015-03-24 09:51:28 -0700499 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800500
501 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
502 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
503 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
504 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
505 EXPECT_TRUE(oat_file_assistant.OatFileExists());
506 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
507 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700508 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800509}
510
David Brazdilce4b0ba2016-01-28 15:05:49 +0000511// Case: We have a DEX file and an extract-only ODEX file out of date relative
512// to the DEX file.
513// Expect: The status is kDex2OatNeeded.
514TEST_F(OatFileAssistantTest, ExtractOnlyOdexOutOfDate) {
515 std::string dex_location = GetScratchDir() + "/ExtractOnlyOdexOutOfDate.jar";
516 std::string odex_location = GetOdexDir() + "/ExtractOnlyOdexOutOfDate.odex";
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 GenerateExtractOnlyOdexForTest(dex_location.c_str(), odex_location.c_str());
522 Copy(GetDexSrc2(), dex_location);
523
524 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
525 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
526
527 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
528 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
529 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
530 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
531 EXPECT_FALSE(oat_file_assistant.OatFileExists());
532 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
533 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
534 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
535}
536
Richard Uhler66d874d2015-01-15 09:37:19 -0800537// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700538// Expect: The status is kPatchOatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800539TEST_F(OatFileAssistantTest, DexOdexNoOat) {
540 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700541 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800542
543 // Create the dex and odex files
544 Copy(GetDexSrc1(), dex_location);
545 GenerateOdexForTest(dex_location, odex_location);
546
547 // Verify the status.
548 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
549
Richard Uhler95abd042015-03-24 09:51:28 -0700550 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800551
552 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
553 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
554 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
555 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
556 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
Richard Uhler66d874d2015-01-15 09:37:19 -0800557 EXPECT_FALSE(oat_file_assistant.OatFileExists());
558 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
559 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700560 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700561
562 // We should still be able to get the non-executable odex file to run from.
563 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
564 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800565}
566
567// Case: We have a stripped DEX file and an ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700568// Expect: The status is kPatchOatNeeded
Richard Uhler66d874d2015-01-15 09:37:19 -0800569TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
570 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700571 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800572
573 // Create the dex and odex files
574 Copy(GetDexSrc1(), dex_location);
575 GenerateOdexForTest(dex_location, odex_location);
576
577 // Strip the dex file
578 Copy(GetStrippedDexSrc1(), dex_location);
579
580 // Verify the status.
581 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
582
Richard Uhler95abd042015-03-24 09:51:28 -0700583 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800584
585 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
586 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
587 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
588 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
589 EXPECT_FALSE(oat_file_assistant.OatFileExists());
590 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
591 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700592 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800593
594 // Make the oat file up to date.
595 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700596 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800597
Richard Uhler95abd042015-03-24 09:51:28 -0700598 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800599
600 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
601 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
602 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
603 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
604 EXPECT_TRUE(oat_file_assistant.OatFileExists());
605 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
606 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700607 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800608
609 // Verify we can load the dex files from it.
610 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
611 ASSERT_TRUE(oat_file.get() != nullptr);
612 EXPECT_TRUE(oat_file->IsExecutable());
613 std::vector<std::unique_ptr<const DexFile>> dex_files;
614 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
615 EXPECT_EQ(1u, dex_files.size());
616}
617
Richard Uhler95abd042015-03-24 09:51:28 -0700618// Case: We have a stripped DEX file, an ODEX file, and an out-of-date OAT file.
619// Expect: The status is kPatchOatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800620TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
621 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700622 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800623
624 // Create the oat file from a different dex file so it looks out of date.
625 Copy(GetDexSrc2(), dex_location);
626 GenerateOatForTest(dex_location.c_str());
627
628 // Create the odex file
629 Copy(GetDexSrc1(), dex_location);
630 GenerateOdexForTest(dex_location, odex_location);
631
632 // Strip the dex file.
633 Copy(GetStrippedDexSrc1(), dex_location);
634
635 // Verify the status.
636 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
637
Richard Uhler95abd042015-03-24 09:51:28 -0700638 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800639
640 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
641 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
642 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
643 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
644 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
645 EXPECT_TRUE(oat_file_assistant.OatFileExists());
646 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
647 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700648 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800649
650 // Make the oat file up to date.
651 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700652 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800653
Richard Uhler95abd042015-03-24 09:51:28 -0700654 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800655
656 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
657 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
658 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
659 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
660 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
661 EXPECT_TRUE(oat_file_assistant.OatFileExists());
662 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
663 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
664 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700665 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800666
667 // Verify we can load the dex files from it.
668 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
669 ASSERT_TRUE(oat_file.get() != nullptr);
670 EXPECT_TRUE(oat_file->IsExecutable());
671 std::vector<std::unique_ptr<const DexFile>> dex_files;
672 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
673 EXPECT_EQ(1u, dex_files.size());
674}
675
Richard Uhler9b994ea2015-06-24 08:44:19 -0700676// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
677// OAT file. Expect: The status is kNoDexOptNeeded.
678TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
679 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
680
681 Copy(GetStrippedDexSrc1(), dex_location);
682
683 // Verify the status.
684 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
685
686 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
687
688 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
689 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
690 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
691 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
692 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
693 EXPECT_FALSE(oat_file_assistant.OatFileExists());
694 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
695 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
696 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
697
698 // Make the oat file up to date. This should have no effect.
699 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700700 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700701
702 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
703
704 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
705 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
706 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
707 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
708 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
709 EXPECT_FALSE(oat_file_assistant.OatFileExists());
710 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
711 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
712 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
713}
714
Richard Uhler95abd042015-03-24 09:51:28 -0700715// Case: We have a DEX file, no ODEX file and an OAT file that needs
716// relocation.
717// Expect: The status is kSelfPatchOatNeeded.
718TEST_F(OatFileAssistantTest, SelfRelocation) {
719 std::string dex_location = GetScratchDir() + "/SelfRelocation.jar";
720 std::string oat_location = GetOdexDir() + "/SelfRelocation.oat";
721
722 // Create the dex and odex files
723 Copy(GetDexSrc1(), dex_location);
724 GenerateOdexForTest(dex_location, oat_location);
725
726 OatFileAssistant oat_file_assistant(dex_location.c_str(),
727 oat_location.c_str(), kRuntimeISA, true);
728
729 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
730
731 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
732 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
733 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
734 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
735 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
736 EXPECT_TRUE(oat_file_assistant.OatFileExists());
737 EXPECT_TRUE(oat_file_assistant.OatFileNeedsRelocation());
738 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
739 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700740 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700741
742 // Make the oat file up to date.
743 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700744 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler95abd042015-03-24 09:51:28 -0700745
746 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
747
748 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
749 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
750 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
751 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
752 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
753 EXPECT_TRUE(oat_file_assistant.OatFileExists());
754 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
755 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
756 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700757 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700758
759 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
760 ASSERT_TRUE(oat_file.get() != nullptr);
761 EXPECT_TRUE(oat_file->IsExecutable());
762 std::vector<std::unique_ptr<const DexFile>> dex_files;
763 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
764 EXPECT_EQ(1u, dex_files.size());
765}
766
Richard Uhler66d874d2015-01-15 09:37:19 -0800767// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
768// OAT files both have patch delta of 0.
Richard Uhler95abd042015-03-24 09:51:28 -0700769// Expect: It shouldn't crash, and status is kPatchOatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800770TEST_F(OatFileAssistantTest, OdexOatOverlap) {
771 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700772 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
773 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -0800774
775 // Create the dex and odex files
776 Copy(GetDexSrc1(), dex_location);
777 GenerateOdexForTest(dex_location, odex_location);
778
779 // Create the oat file by copying the odex so they are located in the same
780 // place in memory.
781 Copy(odex_location, oat_location);
782
783 // Verify things don't go bad.
784 OatFileAssistant oat_file_assistant(dex_location.c_str(),
785 oat_location.c_str(), kRuntimeISA, true);
786
Richard Uhler95abd042015-03-24 09:51:28 -0700787 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800788
789 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
790 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
791 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
792 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
793 EXPECT_TRUE(oat_file_assistant.OatFileExists());
794 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
795 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700796 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800797
798 // Things aren't relocated, so it should fall back to interpreted.
799 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
800 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700801
Richard Uhler66d874d2015-01-15 09:37:19 -0800802 EXPECT_FALSE(oat_file->IsExecutable());
803 std::vector<std::unique_ptr<const DexFile>> dex_files;
804 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
805 EXPECT_EQ(1u, dex_files.size());
806}
807
808// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700809// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
Richard Uhler66d874d2015-01-15 09:37:19 -0800810TEST_F(OatFileAssistantTest, DexPicOdexNoOat) {
811 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700812 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800813
814 // Create the dex and odex files
815 Copy(GetDexSrc1(), dex_location);
816 GeneratePicOdexForTest(dex_location, odex_location);
817
818 // Verify the status.
819 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
820
Richard Uhler95abd042015-03-24 09:51:28 -0700821 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -0800822
823 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
824 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
825 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
826 EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate());
827 EXPECT_FALSE(oat_file_assistant.OatFileExists());
828 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
829 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700830 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800831}
832
David Brazdilce4b0ba2016-01-28 15:05:49 +0000833// Case: We have a DEX file and a ExtractOnly ODEX file, but no OAT file.
834// Expect: The status is kNoDexOptNeeded, because ExtractOnly contains no code.
835TEST_F(OatFileAssistantTest, DexExtractOnlyOdexNoOat) {
836 std::string dex_location = GetScratchDir() + "/DexExtractOnlyOdexNoOat.jar";
837 std::string odex_location = GetOdexDir() + "/DexExtractOnlyOdexNoOat.odex";
838
839 // Create the dex and odex files
840 Copy(GetDexSrc1(), dex_location);
841 GenerateExtractOnlyOdexForTest(dex_location, odex_location);
842
843 // Verify the status.
844 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
845
846 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
847
848 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
849 EXPECT_TRUE(oat_file_assistant.OdexFileExists());
850 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
851 EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate());
852 EXPECT_FALSE(oat_file_assistant.OatFileExists());
853 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
854 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
855 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
856}
857
Richard Uhler66d874d2015-01-15 09:37:19 -0800858// Case: We have a DEX file and up-to-date OAT file for it.
859// Expect: We should load an executable dex file.
860TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
861 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
862
863 Copy(GetDexSrc1(), dex_location);
864 GenerateOatForTest(dex_location.c_str());
865
866 // Load the oat using an oat file assistant.
867 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
868
869 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
870 ASSERT_TRUE(oat_file.get() != nullptr);
871 EXPECT_TRUE(oat_file->IsExecutable());
872 std::vector<std::unique_ptr<const DexFile>> dex_files;
873 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
874 EXPECT_EQ(1u, dex_files.size());
875}
876
877// Case: We have a DEX file and up-to-date OAT file for it.
878// Expect: Loading non-executable should load the oat non-executable.
879TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
880 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
881
882 Copy(GetDexSrc1(), dex_location);
883 GenerateOatForTest(dex_location.c_str());
884
885 // Load the oat using an oat file assistant.
886 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
887
888 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
889 ASSERT_TRUE(oat_file.get() != nullptr);
890 EXPECT_FALSE(oat_file->IsExecutable());
891 std::vector<std::unique_ptr<const DexFile>> dex_files;
892 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
893 EXPECT_EQ(1u, dex_files.size());
894}
895
896// Case: We have a DEX file.
897// Expect: We should load an executable dex file from an alternative oat
898// location.
899TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) {
900 std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar";
901 std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat";
902
903 Copy(GetDexSrc1(), dex_location);
904
905 OatFileAssistant oat_file_assistant(
906 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
907 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700908 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800909
910 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
911 ASSERT_TRUE(oat_file.get() != nullptr);
912 EXPECT_TRUE(oat_file->IsExecutable());
913 std::vector<std::unique_ptr<const DexFile>> dex_files;
914 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
915 EXPECT_EQ(1u, dex_files.size());
916
917 EXPECT_TRUE(OS::FileExists(oat_location.c_str()));
918
919 // Verify it didn't create an oat in the default location.
920 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
921 EXPECT_FALSE(ofm.OatFileExists());
922}
923
Richard Uhler8327cf72015-10-13 16:34:59 -0700924// Case: We have a DEX file but can't write the oat file.
925// Expect: We should fail to make the oat file up to date.
926TEST_F(OatFileAssistantTest, LoadDexUnwriteableAlternateOat) {
927 std::string dex_location = GetScratchDir() + "/LoadDexUnwriteableAlternateOat.jar";
928
929 // Make the oat location unwritable by inserting some non-existent
930 // intermediate directories.
931 std::string oat_location = GetScratchDir() + "/foo/bar/LoadDexUnwriteableAlternateOat.oat";
932
933 Copy(GetDexSrc1(), dex_location);
934
935 OatFileAssistant oat_file_assistant(
936 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
937 std::string error_msg;
938 ASSERT_FALSE(oat_file_assistant.MakeUpToDate(&error_msg));
939
940 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
941 ASSERT_TRUE(oat_file.get() == nullptr);
942}
943
944// Case: We don't have a DEX file and can't write the oat file.
945// Expect: We should fail to generate the oat file without crashing.
946TEST_F(OatFileAssistantTest, GenNoDex) {
947 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
948 std::string oat_location = GetScratchDir() + "/GenNoDex.oat";
949
950 OatFileAssistant oat_file_assistant(
951 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
952 std::string error_msg;
953 ASSERT_FALSE(oat_file_assistant.GenerateOatFile(&error_msg));
954}
955
Richard Uhler66d874d2015-01-15 09:37:19 -0800956// Turn an absolute path into a path relative to the current working
957// directory.
958static std::string MakePathRelative(std::string target) {
959 char buf[MAXPATHLEN];
960 std::string cwd = getcwd(buf, MAXPATHLEN);
961
962 // Split the target and cwd paths into components.
963 std::vector<std::string> target_path;
964 std::vector<std::string> cwd_path;
965 Split(target, '/', &target_path);
966 Split(cwd, '/', &cwd_path);
967
968 // Reverse the path components, so we can use pop_back().
969 std::reverse(target_path.begin(), target_path.end());
970 std::reverse(cwd_path.begin(), cwd_path.end());
971
972 // Drop the common prefix of the paths. Because we reversed the path
973 // components, this becomes the common suffix of target_path and cwd_path.
974 while (!target_path.empty() && !cwd_path.empty()
975 && target_path.back() == cwd_path.back()) {
976 target_path.pop_back();
977 cwd_path.pop_back();
978 }
979
980 // For each element of the remaining cwd_path, add '..' to the beginning
981 // of the target path. Because we reversed the path components, we add to
982 // the end of target_path.
983 for (unsigned int i = 0; i < cwd_path.size(); i++) {
984 target_path.push_back("..");
985 }
986
987 // Reverse again to get the right path order, and join to get the result.
988 std::reverse(target_path.begin(), target_path.end());
989 return Join(target_path, '/');
990}
991
992// Case: Non-absolute path to Dex location.
993// Expect: Not sure, but it shouldn't crash.
994TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
995 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
996 Copy(GetDexSrc1(), abs_dex_location);
997
998 std::string dex_location = MakePathRelative(abs_dex_location);
999 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
1000
1001 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler95abd042015-03-24 09:51:28 -07001002 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -08001003 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
1004 EXPECT_FALSE(oat_file_assistant.OatFileExists());
1005 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
1006 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
1007 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
1008 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
1009}
1010
1011// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001012// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001013TEST_F(OatFileAssistantTest, ShortDexLocation) {
1014 std::string dex_location = "/xx";
1015
1016 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
1017
1018 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001019 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -08001020 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
1021 EXPECT_FALSE(oat_file_assistant.OatFileExists());
1022 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
1023 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
1024 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
1025 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001026 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001027
Richard Uhler9b994ea2015-06-24 08:44:19 -07001028 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -08001029 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001030 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -07001031 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -08001032}
1033
1034// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001035// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001036TEST_F(OatFileAssistantTest, LongDexExtension) {
1037 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1038 Copy(GetDexSrc1(), dex_location);
1039
1040 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
1041
Richard Uhler95abd042015-03-24 09:51:28 -07001042 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded());
Richard Uhler66d874d2015-01-15 09:37:19 -08001043
1044 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
1045 EXPECT_FALSE(oat_file_assistant.OdexFileExists());
1046 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
1047 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
1048 EXPECT_FALSE(oat_file_assistant.OatFileExists());
1049 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
1050 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
1051}
1052
1053// A task to generate a dex location. Used by the RaceToGenerate test.
1054class RaceGenerateTask : public Task {
1055 public:
1056 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
1057 : dex_location_(dex_location), oat_location_(oat_location),
1058 loaded_oat_file_(nullptr)
1059 {}
1060
Roland Levillain4b8f1ec2015-08-26 18:34:03 +01001061 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001062 // Load the dex files, and save a pointer to the loaded oat file, so that
1063 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -08001064 std::vector<std::unique_ptr<const DexFile>> dex_files;
1065 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001066 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001067 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
1068 dex_location_.c_str(),
1069 oat_location_.c_str(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -08001070 /*class_loader*/nullptr,
1071 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001072 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001073 &error_msgs);
Richard Uhler66d874d2015-01-15 09:37:19 -08001074 CHECK(!dex_files.empty()) << Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -07001075 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
1076 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001077 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001078 }
1079
1080 const OatFile* GetLoadedOatFile() const {
1081 return loaded_oat_file_;
1082 }
1083
1084 private:
1085 std::string dex_location_;
1086 std::string oat_location_;
1087 const OatFile* loaded_oat_file_;
1088};
1089
1090// Test the case where multiple processes race to generate an oat file.
1091// This simulates multiple processes using multiple threads.
1092//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001093// We want unique Oat files to be loaded even when there is a race to load.
1094// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1095// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001096TEST_F(OatFileAssistantTest, RaceToGenerate) {
1097 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001098 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001099
1100 // We use the lib core dex file, because it's large, and hopefully should
1101 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001102 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001103
1104 const int kNumThreads = 32;
1105 Thread* self = Thread::Current();
1106 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1107 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1108 for (int i = 0; i < kNumThreads; i++) {
1109 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1110 thread_pool.AddTask(self, task.get());
1111 tasks.push_back(std::move(task));
1112 }
1113 thread_pool.StartWorkers(self);
1114 thread_pool.Wait(self, true, false);
1115
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001116 // Verify every task got a unique oat file.
1117 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001118 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001119 const OatFile* oat_file = task->GetLoadedOatFile();
1120 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1121 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001122 }
1123}
1124
1125// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1126// disabled.
1127// Expect: We should load the odex file non-executable.
1128TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1129 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001130 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001131
1132 // Create the dex and odex files
1133 Copy(GetDexSrc1(), dex_location);
1134 GenerateOdexForTest(dex_location, odex_location);
1135
1136 // Load the oat using an executable oat file assistant.
1137 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
1138
1139 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1140 ASSERT_TRUE(oat_file.get() != nullptr);
1141 EXPECT_FALSE(oat_file->IsExecutable());
1142 std::vector<std::unique_ptr<const DexFile>> dex_files;
1143 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1144 EXPECT_EQ(1u, dex_files.size());
1145}
1146
1147// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1148// disabled.
1149// Expect: We should load the odex file non-executable.
1150TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1151 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001152 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001153
1154 // Create the dex and odex files
1155 Copy(GetMultiDexSrc1(), dex_location);
1156 GenerateOdexForTest(dex_location, odex_location);
1157
1158 // Load the oat using an executable oat file assistant.
1159 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
1160
1161 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1162 ASSERT_TRUE(oat_file.get() != nullptr);
1163 EXPECT_FALSE(oat_file->IsExecutable());
1164 std::vector<std::unique_ptr<const DexFile>> dex_files;
1165 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1166 EXPECT_EQ(2u, dex_files.size());
1167}
1168
1169TEST(OatFileAssistantUtilsTest, DexFilenameToOdexFilename) {
1170 std::string error_msg;
1171 std::string odex_file;
1172
1173 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001174 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001175 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001176
1177 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001178 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001179 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001180
1181 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001182 "nopath.jar", kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001183 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001184 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001185}
1186
Richard Uhler23cedd22015-04-08 13:17:29 -07001187// Verify the dexopt status values from dalvik.system.DexFile
1188// match the OatFileAssistant::DexOptStatus values.
1189TEST_F(OatFileAssistantTest, DexOptStatusValues) {
1190 ScopedObjectAccess soa(Thread::Current());
1191 StackHandleScope<1> hs(soa.Self());
1192 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1193 Handle<mirror::Class> dexfile(
1194 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
1195 ASSERT_FALSE(dexfile.Get() == nullptr);
1196 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1197
Mathieu Chartierc7853442015-03-27 14:35:38 -07001198 ArtField* no_dexopt_needed = mirror::Class::FindStaticField(
Richard Uhler23cedd22015-04-08 13:17:29 -07001199 soa.Self(), dexfile, "NO_DEXOPT_NEEDED", "I");
1200 ASSERT_FALSE(no_dexopt_needed == nullptr);
1201 EXPECT_EQ(no_dexopt_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1202 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, no_dexopt_needed->GetInt(dexfile.Get()));
1203
Mathieu Chartierc7853442015-03-27 14:35:38 -07001204 ArtField* dex2oat_needed = mirror::Class::FindStaticField(
Richard Uhler23cedd22015-04-08 13:17:29 -07001205 soa.Self(), dexfile, "DEX2OAT_NEEDED", "I");
1206 ASSERT_FALSE(dex2oat_needed == nullptr);
1207 EXPECT_EQ(dex2oat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1208 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, dex2oat_needed->GetInt(dexfile.Get()));
1209
Mathieu Chartierc7853442015-03-27 14:35:38 -07001210 ArtField* patchoat_needed = mirror::Class::FindStaticField(
Richard Uhler23cedd22015-04-08 13:17:29 -07001211 soa.Self(), dexfile, "PATCHOAT_NEEDED", "I");
1212 ASSERT_FALSE(patchoat_needed == nullptr);
1213 EXPECT_EQ(patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1214 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, patchoat_needed->GetInt(dexfile.Get()));
1215
Mathieu Chartierc7853442015-03-27 14:35:38 -07001216 ArtField* self_patchoat_needed = mirror::Class::FindStaticField(
Richard Uhler23cedd22015-04-08 13:17:29 -07001217 soa.Self(), dexfile, "SELF_PATCHOAT_NEEDED", "I");
1218 ASSERT_FALSE(self_patchoat_needed == nullptr);
1219 EXPECT_EQ(self_patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1220 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, self_patchoat_needed->GetInt(dexfile.Get()));
1221}
Richard Uhler66d874d2015-01-15 09:37:19 -08001222
1223// TODO: More Tests:
1224// * Test class linker falls back to unquickened dex for DexNoOat
1225// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001226// * Test using secondary isa
1227// * Test with profiling info?
1228// * Test for status of oat while oat is being generated (how?)
1229// * Test case where 32 and 64 bit boot class paths differ,
1230// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1231// 64 bit boot class paths.
1232// * Test unexpected scenarios (?):
1233// - Dex is stripped, don't have odex.
1234// - Oat file corrupted after status check, before reload unexecutable
1235// because it's unrelocated and no dex2oat
1236
1237} // namespace art