blob: 9669dabe2e386db24af635dbf2b3d0fe17635dc0 [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
Richard Uhler66d874d2015-01-15 09:37:19 -080017#include <algorithm>
18#include <fstream>
19#include <string>
20#include <vector>
21#include <sys/param.h>
22
Andreas Gampe9186ced2016-12-12 14:28:21 -080023#include "android-base/strings.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080024#include <backtrace/BacktraceMap.h>
25#include <gtest/gtest.h>
26
Mathieu Chartierc7853442015-03-27 14:35:38 -070027#include "art_field-inl.h"
Vladimir Marko3481ba22015-04-13 12:22:36 +010028#include "class_linker-inl.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080029#include "common_runtime_test.h"
Andreas Gampebb9c6b12015-03-29 13:56:36 -070030#include "compiler_callbacks.h"
Andreas Gampee1459ae2016-06-29 09:36:30 -070031#include "dex2oat_environment_test.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"
Andreas Gampee1459ae2016-06-29 09:36:30 -070034#include "oat_file_assistant.h"
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -070035#include "oat_file_manager.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080036#include "os.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070037#include "scoped_thread_state_change-inl.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080038#include "thread-inl.h"
39#include "utils.h"
40
41namespace art {
42
Andreas Gampee1459ae2016-06-29 09:36:30 -070043class OatFileAssistantTest : public Dex2oatEnvironmentTest {
Richard Uhler66d874d2015-01-15 09:37:19 -080044 public:
Andreas Gampee1459ae2016-06-29 09:36:30 -070045 virtual void SetUp() OVERRIDE {
Richard Uhler66d874d2015-01-15 09:37:19 -080046 ReserveImageSpace();
Andreas Gampee1459ae2016-06-29 09:36:30 -070047 Dex2oatEnvironmentTest::SetUp();
Richard Uhler66d874d2015-01-15 09:37:19 -080048 }
49
Richard Uhlera48403e2016-04-26 10:24:38 -070050 // Pre-Relocate the image to a known non-zero offset so we don't have to
51 // deal with the runtime randomly relocating the image by 0 and messing up
52 // the expected results of the tests.
Richard Uhler03bc6592016-11-22 09:42:04 +000053 bool PreRelocateImage(const std::string& image_location, std::string* error_msg) {
Richard Uhlera48403e2016-04-26 10:24:38 -070054 std::string image;
Richard Uhler03bc6592016-11-22 09:42:04 +000055 if (!GetCachedImageFile(image_location, &image, error_msg)) {
Richard Uhlera48403e2016-04-26 10:24:38 -070056 return false;
57 }
58
59 std::string patchoat = GetAndroidRoot();
60 patchoat += kIsDebugBuild ? "/bin/patchoatd" : "/bin/patchoat";
61
62 std::vector<std::string> argv;
63 argv.push_back(patchoat);
Richard Uhler03bc6592016-11-22 09:42:04 +000064 argv.push_back("--input-image-location=" + image_location);
Richard Uhlera48403e2016-04-26 10:24:38 -070065 argv.push_back("--output-image-file=" + image);
66 argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(kRuntimeISA)));
67 argv.push_back("--base-offset-delta=0x00008000");
68 return Exec(argv, error_msg);
69 }
70
Richard Uhler66d874d2015-01-15 09:37:19 -080071 virtual void PreRuntimeCreate() {
Richard Uhlera48403e2016-04-26 10:24:38 -070072 std::string error_msg;
Richard Uhler03bc6592016-11-22 09:42:04 +000073 ASSERT_TRUE(PreRelocateImage(GetImageLocation(), &error_msg)) << error_msg;
74 ASSERT_TRUE(PreRelocateImage(GetImageLocation2(), &error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -080075 UnreserveImageSpace();
76 }
77
Andreas Gampee1459ae2016-06-29 09:36:30 -070078 virtual void PostRuntimeCreate() OVERRIDE {
Richard Uhler66d874d2015-01-15 09:37:19 -080079 ReserveImageSpace();
80 }
81
Richard Uhler03bc6592016-11-22 09:42:04 +000082 // Generate an oat file for the purposes of test.
83 void GenerateOatForTest(const std::string& dex_location,
84 const std::string& oat_location,
85 CompilerFilter::Filter filter,
86 bool relocate,
87 bool pic,
Richard Uhler03bc6592016-11-22 09:42:04 +000088 bool with_alternate_image) {
David Sehrd106d9f2016-08-16 19:22:57 -070089 std::string dalvik_cache = GetDalvikCache(GetInstructionSetString(kRuntimeISA));
90 std::string dalvik_cache_tmp = dalvik_cache + ".redirected";
Richard Uhler03bc6592016-11-22 09:42:04 +000091
92 if (!relocate) {
93 // Temporarily redirect the dalvik cache so dex2oat doesn't find the
94 // relocated image file.
95 ASSERT_EQ(0, rename(dalvik_cache.c_str(), dalvik_cache_tmp.c_str())) << strerror(errno);
96 }
David Sehrd106d9f2016-08-16 19:22:57 -070097
Richard Uhler93aa2102015-08-10 14:47:41 -070098 std::vector<std::string> args;
99 args.push_back("--dex-file=" + dex_location);
Richard Uhler03bc6592016-11-22 09:42:04 +0000100 args.push_back("--oat-file=" + oat_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000101 args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
Richard Uhlera48403e2016-04-26 10:24:38 -0700102 args.push_back("--runtime-arg");
Richard Uhler03bc6592016-11-22 09:42:04 +0000103
104 // Use -Xnorelocate regardless of the relocate argument.
105 // We control relocation by redirecting the dalvik cache when needed
106 // rather than use this flag.
Richard Uhlera48403e2016-04-26 10:24:38 -0700107 args.push_back("-Xnorelocate");
Richard Uhler93aa2102015-08-10 14:47:41 -0700108
Richard Uhlera48403e2016-04-26 10:24:38 -0700109 if (pic) {
110 args.push_back("--compile-pic");
111 }
112
Richard Uhler03bc6592016-11-22 09:42:04 +0000113 std::string image_location = GetImageLocation();
114 if (with_alternate_image) {
115 args.push_back("--boot-image=" + GetImageLocation2());
116 }
117
Richard Uhler93aa2102015-08-10 14:47:41 -0700118 std::string error_msg;
119 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhler93aa2102015-08-10 14:47:41 -0700120
Richard Uhler03bc6592016-11-22 09:42:04 +0000121 if (!relocate) {
122 // Restore the dalvik cache if needed.
123 ASSERT_EQ(0, rename(dalvik_cache_tmp.c_str(), dalvik_cache.c_str())) << strerror(errno);
124 }
125
126 // Verify the odex file was generated as expected.
127 std::unique_ptr<OatFile> odex_file(OatFile::Open(oat_location.c_str(),
128 oat_location.c_str(),
Mathieu Chartier0b4cbd02016-03-08 16:49:58 -0800129 nullptr,
130 nullptr,
131 false,
132 /*low_4gb*/false,
133 dex_location.c_str(),
134 &error_msg));
Richard Uhler93aa2102015-08-10 14:47:41 -0700135 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
Richard Uhlera48403e2016-04-26 10:24:38 -0700136 EXPECT_EQ(pic, odex_file->IsPic());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000137 EXPECT_EQ(filter, odex_file->GetCompilerFilter());
138
Richard Uhler03bc6592016-11-22 09:42:04 +0000139 std::unique_ptr<ImageHeader> image_header(
140 gc::space::ImageSpace::ReadImageHeader(image_location.c_str(),
141 kRuntimeISA,
142 &error_msg));
143 ASSERT_TRUE(image_header != nullptr) << error_msg;
144 const OatHeader& oat_header = odex_file->GetOatHeader();
145 uint32_t combined_checksum = OatFileAssistant::CalculateCombinedImageChecksum();
146
147 if (CompilerFilter::DependsOnImageChecksum(filter)) {
148 if (with_alternate_image) {
149 EXPECT_NE(combined_checksum, oat_header.GetImageFileLocationOatChecksum());
150 } else {
151 EXPECT_EQ(combined_checksum, oat_header.GetImageFileLocationOatChecksum());
152 }
Andreas Gampe29d38e72016-03-23 15:31:51 +0000153 }
Richard Uhler03bc6592016-11-22 09:42:04 +0000154
Richard Uhlercdcbddf2017-01-19 16:58:39 +0000155 if (!with_alternate_image) {
156 if (CompilerFilter::IsBytecodeCompilationEnabled(filter)) {
157 if (relocate) {
158 EXPECT_EQ(reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin()),
159 oat_header.GetImageFileLocationOatDataBegin());
160 EXPECT_EQ(image_header->GetPatchDelta(), oat_header.GetImagePatchDelta());
161 } else {
162 EXPECT_NE(reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin()),
163 oat_header.GetImageFileLocationOatDataBegin());
164 EXPECT_NE(image_header->GetPatchDelta(), oat_header.GetImagePatchDelta());
165 }
Richard Uhler03bc6592016-11-22 09:42:04 +0000166 }
167 }
168 }
169
170 // Generate a non-PIC odex file for the purposes of test.
171 // The generated odex file will be un-relocated.
172 void GenerateOdexForTest(const std::string& dex_location,
173 const std::string& odex_location,
174 CompilerFilter::Filter filter) {
175 GenerateOatForTest(dex_location,
176 odex_location,
177 filter,
178 /*relocate*/false,
179 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000180 /*with_alternate_image*/false);
Richard Uhler93aa2102015-08-10 14:47:41 -0700181 }
182
183 void GeneratePicOdexForTest(const std::string& dex_location,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000184 const std::string& odex_location,
185 CompilerFilter::Filter filter) {
Richard Uhler03bc6592016-11-22 09:42:04 +0000186 GenerateOatForTest(dex_location,
187 odex_location,
188 filter,
189 /*relocate*/false,
190 /*pic*/true,
Richard Uhler03bc6592016-11-22 09:42:04 +0000191 /*with_alternate_image*/false);
192 }
193
194 // Generate an oat file in the oat location.
195 void GenerateOatForTest(const char* dex_location,
196 CompilerFilter::Filter filter,
197 bool relocate,
198 bool pic,
Richard Uhler03bc6592016-11-22 09:42:04 +0000199 bool with_alternate_image) {
200 std::string oat_location;
201 std::string error_msg;
202 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
203 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
204 GenerateOatForTest(dex_location,
205 oat_location,
206 filter,
207 relocate,
208 pic,
Richard Uhler03bc6592016-11-22 09:42:04 +0000209 with_alternate_image);
210 }
211
212 // Generate a standard oat file in the oat location.
213 void GenerateOatForTest(const char* dex_location, CompilerFilter::Filter filter) {
214 GenerateOatForTest(dex_location,
215 filter,
216 /*relocate*/true,
217 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000218 /*with_alternate_image*/false);
Richard Uhlerd1537b52016-03-29 13:27:41 -0700219 }
220
Richard Uhler66d874d2015-01-15 09:37:19 -0800221 private:
222 // Reserve memory around where the image will be loaded so other memory
223 // won't conflict when it comes time to load the image.
224 // This can be called with an already loaded image to reserve the space
225 // around it.
226 void ReserveImageSpace() {
227 MemMap::Init();
228
229 // Ensure a chunk of memory is reserved for the image space.
Richard Uhlera48403e2016-04-26 10:24:38 -0700230 // The reservation_end includes room for the main space that has to come
231 // right after the image in case of the GSS collector.
232 uintptr_t reservation_start = ART_BASE_ADDRESS;
233 uintptr_t reservation_end = ART_BASE_ADDRESS + 384 * MB;
Richard Uhler66d874d2015-01-15 09:37:19 -0800234
Richard Uhler66d874d2015-01-15 09:37:19 -0800235 std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true));
236 ASSERT_TRUE(map.get() != nullptr) << "Failed to build process map";
237 for (BacktraceMap::const_iterator it = map->begin();
238 reservation_start < reservation_end && it != map->end(); ++it) {
Richard Uhler3efe9792015-03-30 16:18:03 -0700239 ReserveImageSpaceChunk(reservation_start, std::min(it->start, reservation_end));
240 reservation_start = std::max(reservation_start, it->end);
241 }
242 ReserveImageSpaceChunk(reservation_start, reservation_end);
243 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800244
Richard Uhler3efe9792015-03-30 16:18:03 -0700245 // Reserve a chunk of memory for the image space in the given range.
246 // Only has effect for chunks with a positive number of bytes.
247 void ReserveImageSpaceChunk(uintptr_t start, uintptr_t end) {
248 if (start < end) {
249 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800250 image_reservation_.push_back(std::unique_ptr<MemMap>(
251 MemMap::MapAnonymous("image reservation",
Richard Uhler3efe9792015-03-30 16:18:03 -0700252 reinterpret_cast<uint8_t*>(start), end - start,
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700253 PROT_NONE, false, false, &error_msg)));
Richard Uhler66d874d2015-01-15 09:37:19 -0800254 ASSERT_TRUE(image_reservation_.back().get() != nullptr) << error_msg;
255 LOG(INFO) << "Reserved space for image " <<
256 reinterpret_cast<void*>(image_reservation_.back()->Begin()) << "-" <<
257 reinterpret_cast<void*>(image_reservation_.back()->End());
Richard Uhler66d874d2015-01-15 09:37:19 -0800258 }
259 }
260
261
262 // Unreserve any memory reserved by ReserveImageSpace. This should be called
263 // before the image is loaded.
264 void UnreserveImageSpace() {
265 image_reservation_.clear();
266 }
267
Richard Uhler66d874d2015-01-15 09:37:19 -0800268 std::vector<std::unique_ptr<MemMap>> image_reservation_;
269};
270
271class OatFileAssistantNoDex2OatTest : public OatFileAssistantTest {
272 public:
273 virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
274 OatFileAssistantTest::SetUpRuntimeOptions(options);
275 options->push_back(std::make_pair("-Xnodex2oat", nullptr));
276 }
277};
278
Richard Uhler66d874d2015-01-15 09:37:19 -0800279// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700280// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800281TEST_F(OatFileAssistantTest, DexNoOat) {
282 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
283 Copy(GetDexSrc1(), dex_location);
284
Richard Uhlerd1472a22016-04-15 15:18:56 -0700285 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800286
Richard Uhler7225a8d2016-11-22 10:12:03 +0000287 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000288 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000289 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000290 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000291 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000292 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000293 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000294 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800295
296 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000297 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
298 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700299 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800300}
301
302// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700303// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800304TEST_F(OatFileAssistantTest, NoDexNoOat) {
305 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
306
Richard Uhlerd1472a22016-04-15 15:18:56 -0700307 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800308
Andreas Gampe29d38e72016-03-23 15:31:51 +0000309 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
310 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700311 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
312
313 // Trying to make the oat file up to date should not fail or crash.
314 std::string error_msg;
Richard Uhlerd1472a22016-04-15 15:18:56 -0700315 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700316
317 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800318 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
319 EXPECT_EQ(nullptr, oat_file.get());
320}
321
322// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700323// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800324TEST_F(OatFileAssistantTest, OatUpToDate) {
325 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
326 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000327 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800328
Richard Uhlerd1472a22016-04-15 15:18:56 -0700329 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800330
Andreas Gampe29d38e72016-03-23 15:31:51 +0000331 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
332 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
333 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
334 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
335 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
336 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000337 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000338 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
339
Richard Uhler66d874d2015-01-15 09:37:19 -0800340 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000341 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Richard Uhler95abd042015-03-24 09:51:28 -0700342 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700343 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800344}
345
Richard Uhler402089a2017-01-18 08:39:23 +0000346// Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no
347// ODEX file.
348TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) {
349 // This test case is only meaningful if vdex is enabled.
350 if (!kIsVdexEnabled) {
351 return;
352 }
Richard Uhler9a37efc2016-08-05 16:32:55 -0700353
Richard Uhler402089a2017-01-18 08:39:23 +0000354 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar";
355 std::string oat_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat";
356
Richard Uhler9a37efc2016-08-05 16:32:55 -0700357 Copy(GetDexSrc1(), dex_location);
358
Richard Uhler402089a2017-01-18 08:39:23 +0000359 // Generating and deleting the oat file should have the side effect of
360 // creating an up-to-date vdex file.
361 GenerateOdexForTest(dex_location, oat_location, CompilerFilter::kSpeed);
362 ASSERT_EQ(0, unlink(oat_location.c_str()));
363
364 OatFileAssistant oat_file_assistant(dex_location.c_str(),
365 oat_location.c_str(),
366 kRuntimeISA,
367 false);
368
369 // Even though the vdex file is up to date, because we don't have the oat
370 // file, we can't know that the vdex depends on the boot image and is up to
371 // date with respect to the boot image. Instead we must assume the vdex file
372 // depends on the boot image and is out of date with respect to the boot
373 // image.
374 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage,
375 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
376
377 // Make sure we don't crash in this case when we dump the status. We don't
378 // care what the actual dumped value is.
379 oat_file_assistant.GetStatusDump();
380}
381
382// Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT
383// file.
384TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) {
385 // This test case is only meaningful if vdex is enabled.
386 if (!kIsVdexEnabled) {
387 return;
388 }
389
390 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar";
391 std::string oat_location;
392 std::string error_msg;
393 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
394 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
395
396 Copy(GetDexSrc1(), dex_location);
397 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
398 ASSERT_EQ(0, unlink(oat_location.c_str()));
399
Richard Uhler9a37efc2016-08-05 16:32:55 -0700400 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
401
Richard Uhler402089a2017-01-18 08:39:23 +0000402 // Even though the vdex file is up to date, because we don't have the oat
403 // file, we can't know that the vdex depends on the boot image and is up to
404 // date with respect to the boot image. Instead we must assume the vdex file
405 // depends on the boot image and is out of date with respect to the boot
406 // image.
407 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700408 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9a37efc2016-08-05 16:32:55 -0700409}
410
Andreas Gampe29d38e72016-03-23 15:31:51 +0000411// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700412// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
413// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000414TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
415 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
416 Copy(GetDexSrc1(), dex_location);
417 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
418
Richard Uhlerd1472a22016-04-15 15:18:56 -0700419 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000420
421 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700422 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000423 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700424 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000425 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700426 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000427 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700428 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000429
430 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000431 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000432 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
433 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
434}
435
Richard Uhler66d874d2015-01-15 09:37:19 -0800436// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700437// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800438TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
439 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
440 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000441 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800442
Richard Uhlerd1472a22016-04-15 15:18:56 -0700443 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000444 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700445 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700446 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700447
448 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700449 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800450 ASSERT_TRUE(oat_file.get() != nullptr);
451 EXPECT_TRUE(oat_file->IsExecutable());
452 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700453 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
454 EXPECT_EQ(2u, dex_files.size());
455}
456
Richard Uhler67ff7d12015-05-14 13:21:13 -0700457// Case: We have a MultiDEX file where the secondary dex file is out of date.
458// Expect: The status is kDex2OatNeeded.
459TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) {
460 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
461
462 // Compile code for GetMultiDexSrc1.
463 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000464 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700465
466 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
467 // is out of date.
468 Copy(GetMultiDexSrc2(), dex_location);
469
Richard Uhlerd1472a22016-04-15 15:18:56 -0700470 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000471 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700472 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700473 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700474}
475
Richard Uhlere5fed032015-03-18 08:21:11 -0700476// Case: We have a MultiDEX file and up-to-date OAT file for it with relative
477// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700478// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700479TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
480 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700481 std::string oat_location = GetOdexDir() + "/RelativeEncodedDexLocation.oat";
Richard Uhlere5fed032015-03-18 08:21:11 -0700482
483 // Create the dex file
484 Copy(GetMultiDexSrc1(), dex_location);
485
486 // Create the oat file with relative encoded dex location.
487 std::vector<std::string> args;
488 args.push_back("--dex-file=" + dex_location);
489 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
490 args.push_back("--oat-file=" + oat_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000491 args.push_back("--compiler-filter=speed");
Richard Uhlere5fed032015-03-18 08:21:11 -0700492
493 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700494 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700495
496 // Verify we can load both dex files.
497 OatFileAssistant oat_file_assistant(dex_location.c_str(),
498 oat_location.c_str(),
Richard Uhlerd1472a22016-04-15 15:18:56 -0700499 kRuntimeISA, true);
Richard Uhlere5fed032015-03-18 08:21:11 -0700500 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
501 ASSERT_TRUE(oat_file.get() != nullptr);
502 EXPECT_TRUE(oat_file->IsExecutable());
503 std::vector<std::unique_ptr<const DexFile>> dex_files;
504 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800505 EXPECT_EQ(2u, dex_files.size());
506}
507
Richard Uhler03bc6592016-11-22 09:42:04 +0000508// Case: We have a DEX file and an OAT file out of date with respect to the
509// dex checksum.
510TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
511 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800512
513 // We create a dex, generate an oat for it, then overwrite the dex with a
514 // different dex to make the oat out of date.
515 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000516 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800517 Copy(GetDexSrc2(), dex_location);
518
Richard Uhlerd1472a22016-04-15 15:18:56 -0700519 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000520 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000521 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000522 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000523 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800524
525 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000526 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
527 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
528 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
529}
530
Richard Uhler402089a2017-01-18 08:39:23 +0000531// Case: We have a DEX file and an (ODEX) VDEX file out of date with respect
532// to the dex checksum, but no ODEX file.
533TEST_F(OatFileAssistantTest, VdexDexOutOfDate) {
534 // This test case is only meaningful if vdex is enabled.
535 if (!kIsVdexEnabled) {
536 return;
537 }
538
539 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar";
540 std::string oat_location = GetOdexDir() + "/VdexDexOutOfDate.oat";
541
542 Copy(GetDexSrc1(), dex_location);
543 GenerateOdexForTest(dex_location, oat_location, CompilerFilter::kSpeed);
544 ASSERT_EQ(0, unlink(oat_location.c_str()));
545 Copy(GetDexSrc2(), dex_location);
546
547 OatFileAssistant oat_file_assistant(dex_location.c_str(),
548 oat_location.c_str(),
549 kRuntimeISA,
550 false);
551
552 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
553 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
554}
555
556// Case: We have a MultiDEX (ODEX) VDEX file where the secondary dex file is
557// out of date and there is no corresponding ODEX file.
558TEST_F(OatFileAssistantTest, VdexMultiDexSecondaryOutOfDate) {
559 // This test case is only meaningful if vdex is enabled.
560 if (!kIsVdexEnabled) {
561 return;
562 }
563
564 std::string dex_location = GetScratchDir() + "/VdexMultiDexSecondaryOutOfDate.jar";
565 std::string oat_location = GetOdexDir() + "/VdexMultiDexSecondaryOutOfDate.oat";
566
567 Copy(GetMultiDexSrc1(), dex_location);
568 GenerateOdexForTest(dex_location, oat_location, CompilerFilter::kSpeed);
569 ASSERT_EQ(0, unlink(oat_location.c_str()));
570 Copy(GetMultiDexSrc2(), dex_location);
571
572 OatFileAssistant oat_file_assistant(dex_location.c_str(),
573 oat_location.c_str(),
574 kRuntimeISA,
575 false);
576
577 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
578 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
579}
580
Richard Uhler03bc6592016-11-22 09:42:04 +0000581// Case: We have a DEX file and an OAT file out of date with respect to the
582// boot image.
583TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
584 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
585
586 Copy(GetDexSrc1(), dex_location);
587 GenerateOatForTest(dex_location.c_str(),
588 CompilerFilter::kSpeed,
589 /*relocate*/true,
590 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000591 /*with_alternate_image*/true);
592
593 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000594 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000595 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000596 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000597 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000598 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000599 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
600
601 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
602 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
603 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
604 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
605}
606
607// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
608// respect to the boot image.
609// It shouldn't matter that the OAT file is out of date, because it is
610// verify-at-runtime.
611TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
612 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
613
614 Copy(GetDexSrc1(), dex_location);
615 GenerateOatForTest(dex_location.c_str(),
616 CompilerFilter::kVerifyAtRuntime,
617 /*relocate*/true,
618 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000619 /*with_alternate_image*/true);
620
621 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
622 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
623 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000624 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhler03bc6592016-11-22 09:42:04 +0000625 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
626
627 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
628 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
629 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700630 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800631}
632
633// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800634TEST_F(OatFileAssistantTest, DexOdexNoOat) {
635 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700636 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800637
638 // Create the dex and odex files
639 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000640 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800641
642 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700643 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800644
Andreas Gampe29d38e72016-03-23 15:31:51 +0000645 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
646 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler5923b522016-12-08 09:48:01 +0000647 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000648 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800649
650 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000651 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
652 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700653 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700654
655 // We should still be able to get the non-executable odex file to run from.
656 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
657 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800658}
659
Richard Uhler5923b522016-12-08 09:48:01 +0000660// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800661TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
662 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700663 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800664
665 // Create the dex and odex files
666 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000667 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800668
669 // Strip the dex file
670 Copy(GetStrippedDexSrc1(), dex_location);
671
672 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700673 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800674
Richard Uhler5923b522016-12-08 09:48:01 +0000675 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000676 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800677
678 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000679 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000680 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700681 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800682
Richard Uhler66d874d2015-01-15 09:37:19 -0800683 // Verify we can load the dex files from it.
684 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
685 ASSERT_TRUE(oat_file.get() != nullptr);
686 EXPECT_TRUE(oat_file->IsExecutable());
687 std::vector<std::unique_ptr<const DexFile>> dex_files;
688 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
689 EXPECT_EQ(1u, dex_files.size());
690}
691
Richard Uhler5923b522016-12-08 09:48:01 +0000692// Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800693TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
694 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700695 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800696
697 // Create the oat file from a different dex file so it looks out of date.
698 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000699 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800700
701 // Create the odex file
702 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000703 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800704
705 // Strip the dex file.
706 Copy(GetStrippedDexSrc1(), dex_location);
707
708 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700709 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800710
Andreas Gampe29d38e72016-03-23 15:31:51 +0000711 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
712 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000713 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
714 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
715 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, // Can't run dex2oat because dex file is stripped.
716 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800717
718 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000719 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
720 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700721 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800722
723 // Verify we can load the dex files from it.
724 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
725 ASSERT_TRUE(oat_file.get() != nullptr);
726 EXPECT_TRUE(oat_file->IsExecutable());
727 std::vector<std::unique_ptr<const DexFile>> dex_files;
728 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
729 EXPECT_EQ(1u, dex_files.size());
730}
731
Richard Uhler9b994ea2015-06-24 08:44:19 -0700732// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
733// OAT file. Expect: The status is kNoDexOptNeeded.
734TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
735 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
736
737 Copy(GetStrippedDexSrc1(), dex_location);
738
739 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700740 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700741
Andreas Gampe29d38e72016-03-23 15:31:51 +0000742 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
743 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
744 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
745 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
746 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
747 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700748
749 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000750 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
751 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700752 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
753
754 // Make the oat file up to date. This should have no effect.
755 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700756 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700757 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700758 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700759
Andreas Gampe29d38e72016-03-23 15:31:51 +0000760 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
761 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700762
763 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000764 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
765 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700766 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
767}
768
Richard Uhler66d874d2015-01-15 09:37:19 -0800769// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
770// OAT files both have patch delta of 0.
Richard Uhler5923b522016-12-08 09:48:01 +0000771// Expect: It shouldn't crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800772TEST_F(OatFileAssistantTest, OdexOatOverlap) {
773 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700774 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
775 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -0800776
777 // Create the dex and odex files
778 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000779 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800780
781 // Create the oat file by copying the odex so they are located in the same
782 // place in memory.
783 Copy(odex_location, oat_location);
784
785 // Verify things don't go bad.
786 OatFileAssistant oat_file_assistant(dex_location.c_str(),
Richard Uhlerd1472a22016-04-15 15:18:56 -0700787 oat_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800788
Richard Uhler5923b522016-12-08 09:48:01 +0000789 // kDex2OatForRelocation is expected rather than -kDex2OatForRelocation
Richard Uhler7225a8d2016-11-22 10:12:03 +0000790 // based on the assumption that the oat location is more up-to-date than the odex
Richard Uhler70a84262016-11-08 16:51:51 +0000791 // location, even if they both need relocation.
Richard Uhler5923b522016-12-08 09:48:01 +0000792 EXPECT_EQ(OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000793 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800794
795 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000796 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
797 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700798 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800799
800 // Things aren't relocated, so it should fall back to interpreted.
801 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
802 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700803
Richard Uhler66d874d2015-01-15 09:37:19 -0800804 EXPECT_FALSE(oat_file->IsExecutable());
805 std::vector<std::unique_ptr<const DexFile>> dex_files;
806 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
807 EXPECT_EQ(1u, dex_files.size());
808}
809
810// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700811// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
Richard Uhler66d874d2015-01-15 09:37:19 -0800812TEST_F(OatFileAssistantTest, DexPicOdexNoOat) {
813 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700814 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800815
816 // Create the dex and odex files
817 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000818 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800819
820 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700821 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800822
Andreas Gampe29d38e72016-03-23 15:31:51 +0000823 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
824 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000825 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000826 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800827
828 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000829 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000830 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700831 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800832}
833
Andreas Gampe29d38e72016-03-23 15:31:51 +0000834// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
835// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
836TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
837 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
838 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000839
840 // Create the dex and odex files
841 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000842 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerifyAtRuntime);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000843
844 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700845 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000846
Andreas Gampe29d38e72016-03-23 15:31:51 +0000847 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
848 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000849 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000850 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000851
852 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000853 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000854 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000855 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);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000864 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800865
866 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700867 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000868
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 interpret-only OAT file for it.
878// Expect: We should still load the oat file as executable.
879TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
880 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
881
882 Copy(GetDexSrc1(), dex_location);
883 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kInterpretOnly);
884
885 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700886 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800887
888 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
889 ASSERT_TRUE(oat_file.get() != nullptr);
890 EXPECT_TRUE(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 and up-to-date OAT file for it.
897// Expect: Loading non-executable should load the oat non-executable.
898TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
899 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
900
901 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000902 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800903
904 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700905 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800906
907 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
908 ASSERT_TRUE(oat_file.get() != nullptr);
909 EXPECT_FALSE(oat_file->IsExecutable());
910 std::vector<std::unique_ptr<const DexFile>> dex_files;
911 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
912 EXPECT_EQ(1u, dex_files.size());
913}
914
915// Case: We have a DEX file.
916// Expect: We should load an executable dex file from an alternative oat
917// location.
918TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) {
919 std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar";
920 std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat";
921
922 Copy(GetDexSrc1(), dex_location);
923
924 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700925 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800926 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700927 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700928 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700929 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800930
931 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
932 ASSERT_TRUE(oat_file.get() != nullptr);
933 EXPECT_TRUE(oat_file->IsExecutable());
934 std::vector<std::unique_ptr<const DexFile>> dex_files;
935 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
936 EXPECT_EQ(1u, dex_files.size());
937
938 EXPECT_TRUE(OS::FileExists(oat_location.c_str()));
939
940 // Verify it didn't create an oat in the default location.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700941 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler03bc6592016-11-22 09:42:04 +0000942 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800943}
944
Richard Uhler8327cf72015-10-13 16:34:59 -0700945// Case: We have a DEX file but can't write the oat file.
946// Expect: We should fail to make the oat file up to date.
947TEST_F(OatFileAssistantTest, LoadDexUnwriteableAlternateOat) {
948 std::string dex_location = GetScratchDir() + "/LoadDexUnwriteableAlternateOat.jar";
949
950 // Make the oat location unwritable by inserting some non-existent
951 // intermediate directories.
952 std::string oat_location = GetScratchDir() + "/foo/bar/LoadDexUnwriteableAlternateOat.oat";
953
954 Copy(GetDexSrc1(), dex_location);
955
956 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700957 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -0700958 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700959 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700960 ASSERT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700961 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhler8327cf72015-10-13 16:34:59 -0700962
963 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
964 ASSERT_TRUE(oat_file.get() == nullptr);
965}
966
967// Case: We don't have a DEX file and can't write the oat file.
968// Expect: We should fail to generate the oat file without crashing.
969TEST_F(OatFileAssistantTest, GenNoDex) {
970 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
971 std::string oat_location = GetScratchDir() + "/GenNoDex.oat";
972
973 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700974 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -0700975 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700976 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700977 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerf4b34872016-04-13 11:03:46 -0700978 oat_file_assistant.GenerateOatFile(&error_msg));
Richard Uhler8327cf72015-10-13 16:34:59 -0700979}
980
Richard Uhler66d874d2015-01-15 09:37:19 -0800981// Turn an absolute path into a path relative to the current working
982// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -0800983static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800984 char buf[MAXPATHLEN];
985 std::string cwd = getcwd(buf, MAXPATHLEN);
986
987 // Split the target and cwd paths into components.
988 std::vector<std::string> target_path;
989 std::vector<std::string> cwd_path;
990 Split(target, '/', &target_path);
991 Split(cwd, '/', &cwd_path);
992
993 // Reverse the path components, so we can use pop_back().
994 std::reverse(target_path.begin(), target_path.end());
995 std::reverse(cwd_path.begin(), cwd_path.end());
996
997 // Drop the common prefix of the paths. Because we reversed the path
998 // components, this becomes the common suffix of target_path and cwd_path.
999 while (!target_path.empty() && !cwd_path.empty()
1000 && target_path.back() == cwd_path.back()) {
1001 target_path.pop_back();
1002 cwd_path.pop_back();
1003 }
1004
1005 // For each element of the remaining cwd_path, add '..' to the beginning
1006 // of the target path. Because we reversed the path components, we add to
1007 // the end of target_path.
1008 for (unsigned int i = 0; i < cwd_path.size(); i++) {
1009 target_path.push_back("..");
1010 }
1011
1012 // Reverse again to get the right path order, and join to get the result.
1013 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -08001014 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -08001015}
1016
1017// Case: Non-absolute path to Dex location.
1018// Expect: Not sure, but it shouldn't crash.
1019TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
1020 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
1021 Copy(GetDexSrc1(), abs_dex_location);
1022
1023 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -07001024 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001025
1026 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +00001027 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001028 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001029 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1030 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001031}
1032
1033// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -07001034// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001035TEST_F(OatFileAssistantTest, ShortDexLocation) {
1036 std::string dex_location = "/xx";
1037
Richard Uhlerd1472a22016-04-15 15:18:56 -07001038 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001039
1040 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +00001041 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1042 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +00001043 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1044 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -07001045 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -08001046
Richard Uhler9b994ea2015-06-24 08:44:19 -07001047 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -08001048 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001049 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -07001050 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001051 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -07001052 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -08001053}
1054
1055// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -07001056// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -08001057TEST_F(OatFileAssistantTest, LongDexExtension) {
1058 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
1059 Copy(GetDexSrc1(), dex_location);
1060
Richard Uhlerd1472a22016-04-15 15:18:56 -07001061 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -08001062
Richard Uhler7225a8d2016-11-22 10:12:03 +00001063 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +00001064 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -08001065
1066 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +00001067 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
1068 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -08001069}
1070
1071// A task to generate a dex location. Used by the RaceToGenerate test.
1072class RaceGenerateTask : public Task {
1073 public:
1074 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
Jeff Haof0192c82016-03-28 20:39:50 -07001075 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -08001076 {}
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);
Andreas Gampe9186ced2016-12-12 14:28:21 -08001091 CHECK(!dex_files.empty()) << android::base::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);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001151 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001152
1153 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001154 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001155
1156 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1157 ASSERT_TRUE(oat_file.get() != nullptr);
1158 EXPECT_FALSE(oat_file->IsExecutable());
1159 std::vector<std::unique_ptr<const DexFile>> dex_files;
1160 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1161 EXPECT_EQ(1u, dex_files.size());
1162}
1163
1164// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1165// disabled.
1166// Expect: We should load the odex file non-executable.
1167TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1168 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001169 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001170
1171 // Create the dex and odex files
1172 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001173 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001174
1175 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001176 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001177
1178 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1179 ASSERT_TRUE(oat_file.get() != nullptr);
1180 EXPECT_FALSE(oat_file->IsExecutable());
1181 std::vector<std::unique_ptr<const DexFile>> dex_files;
1182 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1183 EXPECT_EQ(2u, dex_files.size());
1184}
1185
Richard Uhlerf4b34872016-04-13 11:03:46 -07001186TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
1187 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
1188 Copy(GetDexSrc1(), dex_location);
1189
Richard Uhlerd1472a22016-04-15 15:18:56 -07001190 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhlerf4b34872016-04-13 11:03:46 -07001191
1192 std::string error_msg;
1193 Runtime::Current()->AddCompilerOption("--compiler-filter=interpret-only");
1194 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001195 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001196 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1197 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler7225a8d2016-11-22 10:12:03 +00001198 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerf4b34872016-04-13 11:03:46 -07001199 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1200
1201 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
1202 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001203 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001204 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1205 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
1206 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1207 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1208
1209 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
1210 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001211 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001212}
1213
Richard Uhlerb81881d2016-04-19 13:08:04 -07001214TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001215 std::string error_msg;
1216 std::string odex_file;
1217
Richard Uhlerb81881d2016-04-19 13:08:04 -07001218 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001219 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001220 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001221
Richard Uhlerb81881d2016-04-19 13:08:04 -07001222 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001223 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001224 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001225
Richard Uhlerb81881d2016-04-19 13:08:04 -07001226 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001227 "nopath.jar", kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001228 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001229 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001230}
1231
Richard Uhler23cedd22015-04-08 13:17:29 -07001232// Verify the dexopt status values from dalvik.system.DexFile
1233// match the OatFileAssistant::DexOptStatus values.
1234TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001235 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1236 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1237 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1238 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1239 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
1240 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001241 };
1242
Richard Uhler23cedd22015-04-08 13:17:29 -07001243 ScopedObjectAccess soa(Thread::Current());
1244 StackHandleScope<1> hs(soa.Self());
1245 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1246 Handle<mirror::Class> dexfile(
1247 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
1248 ASSERT_FALSE(dexfile.Get() == nullptr);
1249 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1250
Richard Uhler7225a8d2016-11-22 10:12:03 +00001251 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1252 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001253 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001254 ASSERT_FALSE(art_field == nullptr);
1255 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1256 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1257 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001258}
Richard Uhler66d874d2015-01-15 09:37:19 -08001259
1260// TODO: More Tests:
1261// * Test class linker falls back to unquickened dex for DexNoOat
1262// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001263// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001264// * Test for status of oat while oat is being generated (how?)
1265// * Test case where 32 and 64 bit boot class paths differ,
1266// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1267// 64 bit boot class paths.
1268// * Test unexpected scenarios (?):
1269// - Dex is stripped, don't have odex.
1270// - Oat file corrupted after status check, before reload unexecutable
1271// because it's unrelocated and no dex2oat
Richard Uhler66d874d2015-01-15 09:37:19 -08001272} // namespace art