blob: afa804c08cc6008b4a6cc812bcdd706986c3c86d [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
155 if (CompilerFilter::IsBytecodeCompilationEnabled(filter)) {
156 if (relocate) {
157 EXPECT_EQ(reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin()),
158 oat_header.GetImageFileLocationOatDataBegin());
159 EXPECT_EQ(image_header->GetPatchDelta(), oat_header.GetImagePatchDelta());
160 } else {
161 EXPECT_NE(reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin()),
162 oat_header.GetImageFileLocationOatDataBegin());
163 EXPECT_NE(image_header->GetPatchDelta(), oat_header.GetImagePatchDelta());
164 }
165 }
166 }
167
168 // Generate a non-PIC odex file for the purposes of test.
169 // The generated odex file will be un-relocated.
170 void GenerateOdexForTest(const std::string& dex_location,
171 const std::string& odex_location,
172 CompilerFilter::Filter filter) {
173 GenerateOatForTest(dex_location,
174 odex_location,
175 filter,
176 /*relocate*/false,
177 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000178 /*with_alternate_image*/false);
Richard Uhler93aa2102015-08-10 14:47:41 -0700179 }
180
181 void GeneratePicOdexForTest(const std::string& dex_location,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000182 const std::string& odex_location,
183 CompilerFilter::Filter filter) {
Richard Uhler03bc6592016-11-22 09:42:04 +0000184 GenerateOatForTest(dex_location,
185 odex_location,
186 filter,
187 /*relocate*/false,
188 /*pic*/true,
Richard Uhler03bc6592016-11-22 09:42:04 +0000189 /*with_alternate_image*/false);
190 }
191
192 // Generate an oat file in the oat location.
193 void GenerateOatForTest(const char* dex_location,
194 CompilerFilter::Filter filter,
195 bool relocate,
196 bool pic,
Richard Uhler03bc6592016-11-22 09:42:04 +0000197 bool with_alternate_image) {
198 std::string oat_location;
199 std::string error_msg;
200 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename(
201 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg;
202 GenerateOatForTest(dex_location,
203 oat_location,
204 filter,
205 relocate,
206 pic,
Richard Uhler03bc6592016-11-22 09:42:04 +0000207 with_alternate_image);
208 }
209
210 // Generate a standard oat file in the oat location.
211 void GenerateOatForTest(const char* dex_location, CompilerFilter::Filter filter) {
212 GenerateOatForTest(dex_location,
213 filter,
214 /*relocate*/true,
215 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000216 /*with_alternate_image*/false);
Richard Uhlerd1537b52016-03-29 13:27:41 -0700217 }
218
Richard Uhler66d874d2015-01-15 09:37:19 -0800219 private:
220 // Reserve memory around where the image will be loaded so other memory
221 // won't conflict when it comes time to load the image.
222 // This can be called with an already loaded image to reserve the space
223 // around it.
224 void ReserveImageSpace() {
225 MemMap::Init();
226
227 // Ensure a chunk of memory is reserved for the image space.
Richard Uhlera48403e2016-04-26 10:24:38 -0700228 // The reservation_end includes room for the main space that has to come
229 // right after the image in case of the GSS collector.
230 uintptr_t reservation_start = ART_BASE_ADDRESS;
231 uintptr_t reservation_end = ART_BASE_ADDRESS + 384 * MB;
Richard Uhler66d874d2015-01-15 09:37:19 -0800232
Richard Uhler66d874d2015-01-15 09:37:19 -0800233 std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true));
234 ASSERT_TRUE(map.get() != nullptr) << "Failed to build process map";
235 for (BacktraceMap::const_iterator it = map->begin();
236 reservation_start < reservation_end && it != map->end(); ++it) {
Richard Uhler3efe9792015-03-30 16:18:03 -0700237 ReserveImageSpaceChunk(reservation_start, std::min(it->start, reservation_end));
238 reservation_start = std::max(reservation_start, it->end);
239 }
240 ReserveImageSpaceChunk(reservation_start, reservation_end);
241 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800242
Richard Uhler3efe9792015-03-30 16:18:03 -0700243 // Reserve a chunk of memory for the image space in the given range.
244 // Only has effect for chunks with a positive number of bytes.
245 void ReserveImageSpaceChunk(uintptr_t start, uintptr_t end) {
246 if (start < end) {
247 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800248 image_reservation_.push_back(std::unique_ptr<MemMap>(
249 MemMap::MapAnonymous("image reservation",
Richard Uhler3efe9792015-03-30 16:18:03 -0700250 reinterpret_cast<uint8_t*>(start), end - start,
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700251 PROT_NONE, false, false, &error_msg)));
Richard Uhler66d874d2015-01-15 09:37:19 -0800252 ASSERT_TRUE(image_reservation_.back().get() != nullptr) << error_msg;
253 LOG(INFO) << "Reserved space for image " <<
254 reinterpret_cast<void*>(image_reservation_.back()->Begin()) << "-" <<
255 reinterpret_cast<void*>(image_reservation_.back()->End());
Richard Uhler66d874d2015-01-15 09:37:19 -0800256 }
257 }
258
259
260 // Unreserve any memory reserved by ReserveImageSpace. This should be called
261 // before the image is loaded.
262 void UnreserveImageSpace() {
263 image_reservation_.clear();
264 }
265
Richard Uhler66d874d2015-01-15 09:37:19 -0800266 std::vector<std::unique_ptr<MemMap>> image_reservation_;
267};
268
269class OatFileAssistantNoDex2OatTest : public OatFileAssistantTest {
270 public:
271 virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
272 OatFileAssistantTest::SetUpRuntimeOptions(options);
273 options->push_back(std::make_pair("-Xnodex2oat", nullptr));
274 }
275};
276
Richard Uhler66d874d2015-01-15 09:37:19 -0800277// Case: We have a DEX file, but no OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700278// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800279TEST_F(OatFileAssistantTest, DexNoOat) {
280 std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
281 Copy(GetDexSrc1(), dex_location);
282
Richard Uhlerd1472a22016-04-15 15:18:56 -0700283 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800284
Richard Uhler7225a8d2016-11-22 10:12:03 +0000285 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000286 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
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::kInterpretOnly));
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::kSpeedProfile));
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::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800293
294 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000295 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
296 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700297 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800298}
299
300// Case: We have no DEX file and no OAT file.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700301// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800302TEST_F(OatFileAssistantTest, NoDexNoOat) {
303 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
304
Richard Uhlerd1472a22016-04-15 15:18:56 -0700305 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800306
Andreas Gampe29d38e72016-03-23 15:31:51 +0000307 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
308 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700309 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
310
311 // Trying to make the oat file up to date should not fail or crash.
312 std::string error_msg;
Richard Uhlerd1472a22016-04-15 15:18:56 -0700313 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700314
315 // Trying to get the best oat file should fail, but not crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800316 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
317 EXPECT_EQ(nullptr, oat_file.get());
318}
319
320// Case: We have a DEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700321// Expect: The status is kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800322TEST_F(OatFileAssistantTest, OatUpToDate) {
323 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
324 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000325 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800326
Richard Uhlerd1472a22016-04-15 15:18:56 -0700327 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800328
Andreas Gampe29d38e72016-03-23 15:31:51 +0000329 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
330 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
331 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
332 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
333 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
334 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000335 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000336 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
337
Richard Uhler66d874d2015-01-15 09:37:19 -0800338 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000339 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Richard Uhler95abd042015-03-24 09:51:28 -0700340 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700341 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800342}
343
Richard Uhler9a37efc2016-08-05 16:32:55 -0700344// Case: We have a DEX file and ODEX file for a different dex location.
345// Expect: The status is kDex2OatNeeded.
346TEST_F(OatFileAssistantTest, OatForDifferentDex) {
347 // Generate an odex file for OatForDifferentDex_A.jar
348 std::string dex_location_a = GetScratchDir() + "/OatForDifferentDex_A.jar";
349 std::string odex_location = GetOdexDir() + "/OatForDifferentDex.odex";
350 Copy(GetDexSrc1(), dex_location_a);
351 GenerateOdexForTest(dex_location_a, odex_location, CompilerFilter::kSpeed);
352
353 // Try to use that odex file for OatForDifferentDex.jar
354 std::string dex_location = GetScratchDir() + "/OatForDifferentDex.jar";
355 Copy(GetDexSrc1(), dex_location);
356
357 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
358
Richard Uhler7225a8d2016-11-22 10:12:03 +0000359 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700360 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
361
362 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000363 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OdexFileStatus());
364 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700365}
366
Andreas Gampe29d38e72016-03-23 15:31:51 +0000367// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700368// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
369// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000370TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
371 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
372 Copy(GetDexSrc1(), dex_location);
373 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
374
Richard Uhlerd1472a22016-04-15 15:18:56 -0700375 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000376
377 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700378 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000379 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700380 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly, false));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000381 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700382 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000383 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700384 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000385
386 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000387 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000388 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
389 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
390}
391
Richard Uhler66d874d2015-01-15 09:37:19 -0800392// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700393// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800394TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
395 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
396 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000397 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800398
Richard Uhlerd1472a22016-04-15 15:18:56 -0700399 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000400 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700401 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700402 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700403
404 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700405 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800406 ASSERT_TRUE(oat_file.get() != nullptr);
407 EXPECT_TRUE(oat_file->IsExecutable());
408 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700409 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
410 EXPECT_EQ(2u, dex_files.size());
411}
412
Richard Uhler67ff7d12015-05-14 13:21:13 -0700413// Case: We have a MultiDEX file where the secondary dex file is out of date.
414// Expect: The status is kDex2OatNeeded.
415TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) {
416 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
417
418 // Compile code for GetMultiDexSrc1.
419 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000420 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700421
422 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
423 // is out of date.
424 Copy(GetMultiDexSrc2(), dex_location);
425
Richard Uhlerd1472a22016-04-15 15:18:56 -0700426 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000427 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700428 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700429 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700430}
431
Richard Uhlere5fed032015-03-18 08:21:11 -0700432// Case: We have a MultiDEX file and up-to-date OAT file for it with relative
433// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700434// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700435TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
436 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700437 std::string oat_location = GetOdexDir() + "/RelativeEncodedDexLocation.oat";
Richard Uhlere5fed032015-03-18 08:21:11 -0700438
439 // Create the dex file
440 Copy(GetMultiDexSrc1(), dex_location);
441
442 // Create the oat file with relative encoded dex location.
443 std::vector<std::string> args;
444 args.push_back("--dex-file=" + dex_location);
445 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
446 args.push_back("--oat-file=" + oat_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000447 args.push_back("--compiler-filter=speed");
Richard Uhlere5fed032015-03-18 08:21:11 -0700448
449 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700450 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700451
452 // Verify we can load both dex files.
453 OatFileAssistant oat_file_assistant(dex_location.c_str(),
454 oat_location.c_str(),
Richard Uhlerd1472a22016-04-15 15:18:56 -0700455 kRuntimeISA, true);
Richard Uhlere5fed032015-03-18 08:21:11 -0700456 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
457 ASSERT_TRUE(oat_file.get() != nullptr);
458 EXPECT_TRUE(oat_file->IsExecutable());
459 std::vector<std::unique_ptr<const DexFile>> dex_files;
460 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800461 EXPECT_EQ(2u, dex_files.size());
462}
463
Richard Uhler03bc6592016-11-22 09:42:04 +0000464// Case: We have a DEX file and an OAT file out of date with respect to the
465// dex checksum.
466TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
467 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800468
469 // We create a dex, generate an oat for it, then overwrite the dex with a
470 // different dex to make the oat out of date.
471 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000472 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800473 Copy(GetDexSrc2(), dex_location);
474
Richard Uhlerd1472a22016-04-15 15:18:56 -0700475 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000476 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000477 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000478 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000479 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800480
481 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000482 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
483 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
484 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
485}
486
487// Case: We have a DEX file and an OAT file out of date with respect to the
488// boot image.
489TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
490 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
491
492 Copy(GetDexSrc1(), dex_location);
493 GenerateOatForTest(dex_location.c_str(),
494 CompilerFilter::kSpeed,
495 /*relocate*/true,
496 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000497 /*with_alternate_image*/true);
498
499 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000500 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000501 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000502 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000503 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000504 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000505 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
506
507 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
508 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
509 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
510 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
511}
512
513// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
514// respect to the boot image.
515// It shouldn't matter that the OAT file is out of date, because it is
516// verify-at-runtime.
517TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
518 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
519
520 Copy(GetDexSrc1(), dex_location);
521 GenerateOatForTest(dex_location.c_str(),
522 CompilerFilter::kVerifyAtRuntime,
523 /*relocate*/true,
524 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000525 /*with_alternate_image*/true);
526
527 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
528 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
529 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000530 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhler03bc6592016-11-22 09:42:04 +0000531 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
532
533 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
534 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
535 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700536 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800537}
538
539// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800540TEST_F(OatFileAssistantTest, DexOdexNoOat) {
541 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700542 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800543
544 // Create the dex and odex files
545 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000546 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800547
548 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700549 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800550
Andreas Gampe29d38e72016-03-23 15:31:51 +0000551 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
552 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler5923b522016-12-08 09:48:01 +0000553 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000554 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800555
556 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000557 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
558 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700559 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700560
561 // We should still be able to get the non-executable odex file to run from.
562 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
563 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800564}
565
Richard Uhler5923b522016-12-08 09:48:01 +0000566// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800567TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
568 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700569 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800570
571 // Create the dex and odex files
572 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000573 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800574
575 // Strip the dex file
576 Copy(GetStrippedDexSrc1(), dex_location);
577
578 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700579 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800580
Richard Uhler5923b522016-12-08 09:48:01 +0000581 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000582 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800583
584 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000585 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000586 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700587 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800588
Richard Uhler66d874d2015-01-15 09:37:19 -0800589 // Verify we can load the dex files from it.
590 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
591 ASSERT_TRUE(oat_file.get() != nullptr);
592 EXPECT_TRUE(oat_file->IsExecutable());
593 std::vector<std::unique_ptr<const DexFile>> dex_files;
594 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
595 EXPECT_EQ(1u, dex_files.size());
596}
597
Richard Uhler5923b522016-12-08 09:48:01 +0000598// 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 -0800599TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
600 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700601 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800602
603 // Create the oat file from a different dex file so it looks out of date.
604 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000605 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800606
607 // Create the odex file
608 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000609 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800610
611 // Strip the dex file.
612 Copy(GetStrippedDexSrc1(), dex_location);
613
614 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700615 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800616
Andreas Gampe29d38e72016-03-23 15:31:51 +0000617 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
618 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000619 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
620 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
621 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, // Can't run dex2oat because dex file is stripped.
622 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800623
624 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000625 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
626 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700627 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800628
629 // Verify we can load the dex files from it.
630 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
631 ASSERT_TRUE(oat_file.get() != nullptr);
632 EXPECT_TRUE(oat_file->IsExecutable());
633 std::vector<std::unique_ptr<const DexFile>> dex_files;
634 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
635 EXPECT_EQ(1u, dex_files.size());
636}
637
Richard Uhler9b994ea2015-06-24 08:44:19 -0700638// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
639// OAT file. Expect: The status is kNoDexOptNeeded.
640TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
641 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
642
643 Copy(GetStrippedDexSrc1(), dex_location);
644
645 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700646 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700647
Andreas Gampe29d38e72016-03-23 15:31:51 +0000648 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
649 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
650 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
651 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
652 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
653 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700654
655 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000656 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
657 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700658 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
659
660 // Make the oat file up to date. This should have no effect.
661 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700662 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700663 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700664 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700665
Andreas Gampe29d38e72016-03-23 15:31:51 +0000666 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
667 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700668
669 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000670 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
671 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700672 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
673}
674
Richard Uhler66d874d2015-01-15 09:37:19 -0800675// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
676// OAT files both have patch delta of 0.
Richard Uhler5923b522016-12-08 09:48:01 +0000677// Expect: It shouldn't crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800678TEST_F(OatFileAssistantTest, OdexOatOverlap) {
679 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700680 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
681 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -0800682
683 // Create the dex and odex files
684 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000685 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800686
687 // Create the oat file by copying the odex so they are located in the same
688 // place in memory.
689 Copy(odex_location, oat_location);
690
691 // Verify things don't go bad.
692 OatFileAssistant oat_file_assistant(dex_location.c_str(),
Richard Uhlerd1472a22016-04-15 15:18:56 -0700693 oat_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800694
Richard Uhler5923b522016-12-08 09:48:01 +0000695 // kDex2OatForRelocation is expected rather than -kDex2OatForRelocation
Richard Uhler7225a8d2016-11-22 10:12:03 +0000696 // based on the assumption that the oat location is more up-to-date than the odex
Richard Uhler70a84262016-11-08 16:51:51 +0000697 // location, even if they both need relocation.
Richard Uhler5923b522016-12-08 09:48:01 +0000698 EXPECT_EQ(OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000699 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800700
701 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000702 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
703 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700704 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800705
706 // Things aren't relocated, so it should fall back to interpreted.
707 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
708 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700709
Richard Uhler66d874d2015-01-15 09:37:19 -0800710 EXPECT_FALSE(oat_file->IsExecutable());
711 std::vector<std::unique_ptr<const DexFile>> dex_files;
712 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
713 EXPECT_EQ(1u, dex_files.size());
714}
715
716// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700717// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
Richard Uhler66d874d2015-01-15 09:37:19 -0800718TEST_F(OatFileAssistantTest, DexPicOdexNoOat) {
719 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700720 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800721
722 // Create the dex and odex files
723 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000724 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800725
726 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700727 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800728
Andreas Gampe29d38e72016-03-23 15:31:51 +0000729 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
730 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000731 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000732 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800733
734 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000735 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000736 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700737 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800738}
739
Andreas Gampe29d38e72016-03-23 15:31:51 +0000740// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
741// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
742TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
743 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
744 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000745
746 // Create the dex and odex files
747 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000748 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerifyAtRuntime);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000749
750 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700751 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000752
Andreas Gampe29d38e72016-03-23 15:31:51 +0000753 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
754 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000755 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000756 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000757
758 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000759 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000760 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000761 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
762}
763
Richard Uhler66d874d2015-01-15 09:37:19 -0800764// Case: We have a DEX file and up-to-date OAT file for it.
765// Expect: We should load an executable dex file.
766TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
767 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
768
769 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000770 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800771
772 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700773 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000774
775 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
776 ASSERT_TRUE(oat_file.get() != nullptr);
777 EXPECT_TRUE(oat_file->IsExecutable());
778 std::vector<std::unique_ptr<const DexFile>> dex_files;
779 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
780 EXPECT_EQ(1u, dex_files.size());
781}
782
783// Case: We have a DEX file and up-to-date interpret-only OAT file for it.
784// Expect: We should still load the oat file as executable.
785TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
786 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
787
788 Copy(GetDexSrc1(), dex_location);
789 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kInterpretOnly);
790
791 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700792 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800793
794 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
795 ASSERT_TRUE(oat_file.get() != nullptr);
796 EXPECT_TRUE(oat_file->IsExecutable());
797 std::vector<std::unique_ptr<const DexFile>> dex_files;
798 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
799 EXPECT_EQ(1u, dex_files.size());
800}
801
802// Case: We have a DEX file and up-to-date OAT file for it.
803// Expect: Loading non-executable should load the oat non-executable.
804TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
805 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
806
807 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000808 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800809
810 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700811 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800812
813 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
814 ASSERT_TRUE(oat_file.get() != nullptr);
815 EXPECT_FALSE(oat_file->IsExecutable());
816 std::vector<std::unique_ptr<const DexFile>> dex_files;
817 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
818 EXPECT_EQ(1u, dex_files.size());
819}
820
821// Case: We have a DEX file.
822// Expect: We should load an executable dex file from an alternative oat
823// location.
824TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) {
825 std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar";
826 std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat";
827
828 Copy(GetDexSrc1(), dex_location);
829
830 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700831 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800832 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700833 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700834 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700835 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800836
837 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
838 ASSERT_TRUE(oat_file.get() != nullptr);
839 EXPECT_TRUE(oat_file->IsExecutable());
840 std::vector<std::unique_ptr<const DexFile>> dex_files;
841 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
842 EXPECT_EQ(1u, dex_files.size());
843
844 EXPECT_TRUE(OS::FileExists(oat_location.c_str()));
845
846 // Verify it didn't create an oat in the default location.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700847 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler03bc6592016-11-22 09:42:04 +0000848 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800849}
850
Richard Uhler8327cf72015-10-13 16:34:59 -0700851// Case: We have a DEX file but can't write the oat file.
852// Expect: We should fail to make the oat file up to date.
853TEST_F(OatFileAssistantTest, LoadDexUnwriteableAlternateOat) {
854 std::string dex_location = GetScratchDir() + "/LoadDexUnwriteableAlternateOat.jar";
855
856 // Make the oat location unwritable by inserting some non-existent
857 // intermediate directories.
858 std::string oat_location = GetScratchDir() + "/foo/bar/LoadDexUnwriteableAlternateOat.oat";
859
860 Copy(GetDexSrc1(), dex_location);
861
862 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700863 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -0700864 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700865 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700866 ASSERT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700867 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhler8327cf72015-10-13 16:34:59 -0700868
869 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
870 ASSERT_TRUE(oat_file.get() == nullptr);
871}
872
873// Case: We don't have a DEX file and can't write the oat file.
874// Expect: We should fail to generate the oat file without crashing.
875TEST_F(OatFileAssistantTest, GenNoDex) {
876 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
877 std::string oat_location = GetScratchDir() + "/GenNoDex.oat";
878
879 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700880 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -0700881 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700882 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700883 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerf4b34872016-04-13 11:03:46 -0700884 oat_file_assistant.GenerateOatFile(&error_msg));
Richard Uhler8327cf72015-10-13 16:34:59 -0700885}
886
Richard Uhler66d874d2015-01-15 09:37:19 -0800887// Turn an absolute path into a path relative to the current working
888// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -0800889static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800890 char buf[MAXPATHLEN];
891 std::string cwd = getcwd(buf, MAXPATHLEN);
892
893 // Split the target and cwd paths into components.
894 std::vector<std::string> target_path;
895 std::vector<std::string> cwd_path;
896 Split(target, '/', &target_path);
897 Split(cwd, '/', &cwd_path);
898
899 // Reverse the path components, so we can use pop_back().
900 std::reverse(target_path.begin(), target_path.end());
901 std::reverse(cwd_path.begin(), cwd_path.end());
902
903 // Drop the common prefix of the paths. Because we reversed the path
904 // components, this becomes the common suffix of target_path and cwd_path.
905 while (!target_path.empty() && !cwd_path.empty()
906 && target_path.back() == cwd_path.back()) {
907 target_path.pop_back();
908 cwd_path.pop_back();
909 }
910
911 // For each element of the remaining cwd_path, add '..' to the beginning
912 // of the target path. Because we reversed the path components, we add to
913 // the end of target_path.
914 for (unsigned int i = 0; i < cwd_path.size(); i++) {
915 target_path.push_back("..");
916 }
917
918 // Reverse again to get the right path order, and join to get the result.
919 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -0800920 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -0800921}
922
923// Case: Non-absolute path to Dex location.
924// Expect: Not sure, but it shouldn't crash.
925TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
926 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
927 Copy(GetDexSrc1(), abs_dex_location);
928
929 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -0700930 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800931
932 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +0000933 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000934 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +0000935 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
936 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800937}
938
939// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700940// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800941TEST_F(OatFileAssistantTest, ShortDexLocation) {
942 std::string dex_location = "/xx";
943
Richard Uhlerd1472a22016-04-15 15:18:56 -0700944 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800945
946 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000947 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
948 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +0000949 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
950 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700951 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800952
Richard Uhler9b994ea2015-06-24 08:44:19 -0700953 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -0800954 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700955 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700956 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700957 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700958 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -0800959}
960
961// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -0700962// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800963TEST_F(OatFileAssistantTest, LongDexExtension) {
964 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
965 Copy(GetDexSrc1(), dex_location);
966
Richard Uhlerd1472a22016-04-15 15:18:56 -0700967 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800968
Richard Uhler7225a8d2016-11-22 10:12:03 +0000969 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000970 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800971
972 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000973 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
974 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800975}
976
977// A task to generate a dex location. Used by the RaceToGenerate test.
978class RaceGenerateTask : public Task {
979 public:
980 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
Jeff Haof0192c82016-03-28 20:39:50 -0700981 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -0800982 {}
983
Roland Levillain4b8f1ec2015-08-26 18:34:03 +0100984 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800985 // Load the dex files, and save a pointer to the loaded oat file, so that
986 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -0800987 std::vector<std::unique_ptr<const DexFile>> dex_files;
988 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700989 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -0700990 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
991 dex_location_.c_str(),
992 oat_location_.c_str(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800993 /*class_loader*/nullptr,
994 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700995 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -0700996 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -0800997 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -0700998 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
999 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001000 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001001 }
1002
1003 const OatFile* GetLoadedOatFile() const {
1004 return loaded_oat_file_;
1005 }
1006
1007 private:
1008 std::string dex_location_;
1009 std::string oat_location_;
1010 const OatFile* loaded_oat_file_;
1011};
1012
1013// Test the case where multiple processes race to generate an oat file.
1014// This simulates multiple processes using multiple threads.
1015//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001016// We want unique Oat files to be loaded even when there is a race to load.
1017// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1018// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001019TEST_F(OatFileAssistantTest, RaceToGenerate) {
1020 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001021 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001022
1023 // We use the lib core dex file, because it's large, and hopefully should
1024 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001025 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001026
1027 const int kNumThreads = 32;
1028 Thread* self = Thread::Current();
1029 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1030 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1031 for (int i = 0; i < kNumThreads; i++) {
1032 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1033 thread_pool.AddTask(self, task.get());
1034 tasks.push_back(std::move(task));
1035 }
1036 thread_pool.StartWorkers(self);
1037 thread_pool.Wait(self, true, false);
1038
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001039 // Verify every task got a unique oat file.
1040 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001041 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001042 const OatFile* oat_file = task->GetLoadedOatFile();
1043 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1044 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001045 }
1046}
1047
1048// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1049// disabled.
1050// Expect: We should load the odex file non-executable.
1051TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1052 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001053 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001054
1055 // Create the dex and odex files
1056 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001057 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001058
1059 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001060 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001061
1062 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1063 ASSERT_TRUE(oat_file.get() != nullptr);
1064 EXPECT_FALSE(oat_file->IsExecutable());
1065 std::vector<std::unique_ptr<const DexFile>> dex_files;
1066 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1067 EXPECT_EQ(1u, dex_files.size());
1068}
1069
1070// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1071// disabled.
1072// Expect: We should load the odex file non-executable.
1073TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1074 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001075 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001076
1077 // Create the dex and odex files
1078 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001079 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001080
1081 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001082 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001083
1084 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1085 ASSERT_TRUE(oat_file.get() != nullptr);
1086 EXPECT_FALSE(oat_file->IsExecutable());
1087 std::vector<std::unique_ptr<const DexFile>> dex_files;
1088 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1089 EXPECT_EQ(2u, dex_files.size());
1090}
1091
Richard Uhlerf4b34872016-04-13 11:03:46 -07001092TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
1093 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
1094 Copy(GetDexSrc1(), dex_location);
1095
Richard Uhlerd1472a22016-04-15 15:18:56 -07001096 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhlerf4b34872016-04-13 11:03:46 -07001097
1098 std::string error_msg;
1099 Runtime::Current()->AddCompilerOption("--compiler-filter=interpret-only");
1100 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001101 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001102 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1103 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler7225a8d2016-11-22 10:12:03 +00001104 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerf4b34872016-04-13 11:03:46 -07001105 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1106
1107 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
1108 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001109 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001110 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1111 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
1112 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1113 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1114
1115 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
1116 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001117 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001118}
1119
Richard Uhlerb81881d2016-04-19 13:08:04 -07001120TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001121 std::string error_msg;
1122 std::string odex_file;
1123
Richard Uhlerb81881d2016-04-19 13:08:04 -07001124 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001125 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001126 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001127
Richard Uhlerb81881d2016-04-19 13:08:04 -07001128 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001129 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001130 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001131
Richard Uhlerb81881d2016-04-19 13:08:04 -07001132 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001133 "nopath.jar", kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001134 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001135 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001136}
1137
Richard Uhler23cedd22015-04-08 13:17:29 -07001138// Verify the dexopt status values from dalvik.system.DexFile
1139// match the OatFileAssistant::DexOptStatus values.
1140TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001141 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1142 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1143 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1144 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1145 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
1146 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001147 };
1148
Richard Uhler23cedd22015-04-08 13:17:29 -07001149 ScopedObjectAccess soa(Thread::Current());
1150 StackHandleScope<1> hs(soa.Self());
1151 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1152 Handle<mirror::Class> dexfile(
1153 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
1154 ASSERT_FALSE(dexfile.Get() == nullptr);
1155 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1156
Richard Uhler7225a8d2016-11-22 10:12:03 +00001157 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1158 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001159 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001160 ASSERT_FALSE(art_field == nullptr);
1161 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1162 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1163 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001164}
Richard Uhler66d874d2015-01-15 09:37:19 -08001165
1166// TODO: More Tests:
1167// * Test class linker falls back to unquickened dex for DexNoOat
1168// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001169// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001170// * Test for status of oat while oat is being generated (how?)
1171// * Test case where 32 and 64 bit boot class paths differ,
1172// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1173// 64 bit boot class paths.
1174// * Test unexpected scenarios (?):
1175// - Dex is stripped, don't have odex.
1176// - Oat file corrupted after status check, before reload unexecutable
1177// because it's unrelocated and no dex2oat
Calin Juravleb077e152016-02-18 18:47:37 +00001178// * Test unrelocated specific target compilation type can be relocated to
1179// make it up to date.
Richard Uhler66d874d2015-01-15 09:37:19 -08001180} // namespace art