blob: 84eacde8b7b46283afab8df0e009a02812c93d9d [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 Uhler9a37efc2016-08-05 16:32:55 -0700346// Case: We have a DEX file and ODEX file for a different dex location.
347// Expect: The status is kDex2OatNeeded.
348TEST_F(OatFileAssistantTest, OatForDifferentDex) {
349 // Generate an odex file for OatForDifferentDex_A.jar
350 std::string dex_location_a = GetScratchDir() + "/OatForDifferentDex_A.jar";
351 std::string odex_location = GetOdexDir() + "/OatForDifferentDex.odex";
352 Copy(GetDexSrc1(), dex_location_a);
353 GenerateOdexForTest(dex_location_a, odex_location, CompilerFilter::kSpeed);
354
355 // Try to use that odex file for OatForDifferentDex.jar
356 std::string dex_location = GetScratchDir() + "/OatForDifferentDex.jar";
357 Copy(GetDexSrc1(), dex_location);
358
359 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
360
Richard Uhler7225a8d2016-11-22 10:12:03 +0000361 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhler9a37efc2016-08-05 16:32:55 -0700362 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
363
364 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000365 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OdexFileStatus());
366 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9a37efc2016-08-05 16:32:55 -0700367}
368
Andreas Gampe29d38e72016-03-23 15:31:51 +0000369// Case: We have a DEX file and speed-profile OAT file for it.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700370// Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but
371// kDex2Oat if the profile has changed.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000372TEST_F(OatFileAssistantTest, ProfileOatUpToDate) {
373 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar";
374 Copy(GetDexSrc1(), dex_location);
375 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile);
376
Richard Uhlerd1472a22016-04-15 15:18:56 -0700377 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000378
379 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700380 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000381 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700382 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly, false));
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::kSpeedProfile, true));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000385 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700386 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly, true));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000387
388 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000389 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000390 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
391 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
392}
393
Richard Uhler66d874d2015-01-15 09:37:19 -0800394// Case: We have a MultiDEX file and up-to-date OAT file for it.
Richard Uhler95abd042015-03-24 09:51:28 -0700395// Expect: The status is kNoDexOptNeeded and we load all dex files.
Richard Uhler66d874d2015-01-15 09:37:19 -0800396TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
397 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
398 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000399 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800400
Richard Uhlerd1472a22016-04-15 15:18:56 -0700401 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000402 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700403 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700404 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler95abd042015-03-24 09:51:28 -0700405
406 // Verify we can load both dex files.
Richard Uhlere5fed032015-03-18 08:21:11 -0700407 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800408 ASSERT_TRUE(oat_file.get() != nullptr);
409 EXPECT_TRUE(oat_file->IsExecutable());
410 std::vector<std::unique_ptr<const DexFile>> dex_files;
Richard Uhlere5fed032015-03-18 08:21:11 -0700411 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
412 EXPECT_EQ(2u, dex_files.size());
413}
414
Richard Uhler67ff7d12015-05-14 13:21:13 -0700415// Case: We have a MultiDEX file where the secondary dex file is out of date.
416// Expect: The status is kDex2OatNeeded.
417TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) {
418 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar";
419
420 // Compile code for GetMultiDexSrc1.
421 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000422 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler67ff7d12015-05-14 13:21:13 -0700423
424 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum
425 // is out of date.
426 Copy(GetMultiDexSrc2(), dex_location);
427
Richard Uhlerd1472a22016-04-15 15:18:56 -0700428 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000429 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700430 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700431 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler67ff7d12015-05-14 13:21:13 -0700432}
433
Richard Uhlere5fed032015-03-18 08:21:11 -0700434// Case: We have a MultiDEX file and up-to-date OAT file for it with relative
435// encoded dex locations.
Richard Uhler95abd042015-03-24 09:51:28 -0700436// Expect: The oat file status is kNoDexOptNeeded.
Richard Uhlere5fed032015-03-18 08:21:11 -0700437TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) {
438 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700439 std::string oat_location = GetOdexDir() + "/RelativeEncodedDexLocation.oat";
Richard Uhlere5fed032015-03-18 08:21:11 -0700440
441 // Create the dex file
442 Copy(GetMultiDexSrc1(), dex_location);
443
444 // Create the oat file with relative encoded dex location.
445 std::vector<std::string> args;
446 args.push_back("--dex-file=" + dex_location);
447 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar"));
448 args.push_back("--oat-file=" + oat_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000449 args.push_back("--compiler-filter=speed");
Richard Uhlere5fed032015-03-18 08:21:11 -0700450
451 std::string error_msg;
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700452 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
Richard Uhlere5fed032015-03-18 08:21:11 -0700453
454 // Verify we can load both dex files.
455 OatFileAssistant oat_file_assistant(dex_location.c_str(),
456 oat_location.c_str(),
Richard Uhlerd1472a22016-04-15 15:18:56 -0700457 kRuntimeISA, true);
Richard Uhlere5fed032015-03-18 08:21:11 -0700458 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
459 ASSERT_TRUE(oat_file.get() != nullptr);
460 EXPECT_TRUE(oat_file->IsExecutable());
461 std::vector<std::unique_ptr<const DexFile>> dex_files;
462 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800463 EXPECT_EQ(2u, dex_files.size());
464}
465
Richard Uhler03bc6592016-11-22 09:42:04 +0000466// Case: We have a DEX file and an OAT file out of date with respect to the
467// dex checksum.
468TEST_F(OatFileAssistantTest, OatDexOutOfDate) {
469 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800470
471 // We create a dex, generate an oat for it, then overwrite the dex with a
472 // different dex to make the oat out of date.
473 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000474 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800475 Copy(GetDexSrc2(), dex_location);
476
Richard Uhlerd1472a22016-04-15 15:18:56 -0700477 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
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::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000480 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000481 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800482
483 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000484 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
485 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
486 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
487}
488
489// Case: We have a DEX file and an OAT file out of date with respect to the
490// boot image.
491TEST_F(OatFileAssistantTest, OatImageOutOfDate) {
492 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar";
493
494 Copy(GetDexSrc1(), dex_location);
495 GenerateOatForTest(dex_location.c_str(),
496 CompilerFilter::kSpeed,
497 /*relocate*/true,
498 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000499 /*with_alternate_image*/true);
500
501 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
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::kVerifyAtRuntime));
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::kInterpretOnly));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000506 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage,
Richard Uhler03bc6592016-11-22 09:42:04 +0000507 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
508
509 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
510 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
511 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus());
512 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
513}
514
515// Case: We have a DEX file and a verify-at-runtime OAT file out of date with
516// respect to the boot image.
517// It shouldn't matter that the OAT file is out of date, because it is
518// verify-at-runtime.
519TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) {
520 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar";
521
522 Copy(GetDexSrc1(), dex_location);
523 GenerateOatForTest(dex_location.c_str(),
524 CompilerFilter::kVerifyAtRuntime,
525 /*relocate*/true,
526 /*pic*/false,
Richard Uhler03bc6592016-11-22 09:42:04 +0000527 /*with_alternate_image*/true);
528
529 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
530 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
531 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000532 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhler03bc6592016-11-22 09:42:04 +0000533 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
534
535 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
536 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
537 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700538 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800539}
540
541// Case: We have a DEX file and an ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800542TEST_F(OatFileAssistantTest, DexOdexNoOat) {
543 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700544 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800545
546 // Create the dex and odex files
547 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000548 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800549
550 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700551 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800552
Andreas Gampe29d38e72016-03-23 15:31:51 +0000553 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
554 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler5923b522016-12-08 09:48:01 +0000555 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000556 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800557
558 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000559 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
560 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700561 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler5f946da2015-07-17 12:28:32 -0700562
563 // We should still be able to get the non-executable odex file to run from.
564 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
565 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800566}
567
Richard Uhler5923b522016-12-08 09:48:01 +0000568// Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler66d874d2015-01-15 09:37:19 -0800569TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
570 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700571 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800572
573 // Create the dex and odex files
574 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000575 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800576
577 // Strip the dex file
578 Copy(GetStrippedDexSrc1(), dex_location);
579
580 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700581 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800582
Richard Uhler5923b522016-12-08 09:48:01 +0000583 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000584 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800585
586 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000587 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000588 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700589 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800590
Richard Uhler66d874d2015-01-15 09:37:19 -0800591 // Verify we can load the dex files from it.
592 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
593 ASSERT_TRUE(oat_file.get() != nullptr);
594 EXPECT_TRUE(oat_file->IsExecutable());
595 std::vector<std::unique_ptr<const DexFile>> dex_files;
596 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
597 EXPECT_EQ(1u, dex_files.size());
598}
599
Richard Uhler5923b522016-12-08 09:48:01 +0000600// 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 -0800601TEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
602 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700603 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800604
605 // Create the oat file from a different dex file so it looks out of date.
606 Copy(GetDexSrc2(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000607 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800608
609 // Create the odex file
610 Copy(GetDexSrc1(), dex_location);
Richard Uhler5923b522016-12-08 09:48:01 +0000611 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800612
613 // Strip the dex file.
614 Copy(GetStrippedDexSrc1(), dex_location);
615
616 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700617 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800618
Andreas Gampe29d38e72016-03-23 15:31:51 +0000619 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
620 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Andreas Gampe29d38e72016-03-23 15:31:51 +0000621 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
622 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
623 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, // Can't run dex2oat because dex file is stripped.
624 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800625
626 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler5923b522016-12-08 09:48:01 +0000627 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
628 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700629 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800630
631 // Verify we can load the dex files from it.
632 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
633 ASSERT_TRUE(oat_file.get() != nullptr);
634 EXPECT_TRUE(oat_file->IsExecutable());
635 std::vector<std::unique_ptr<const DexFile>> dex_files;
636 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
637 EXPECT_EQ(1u, dex_files.size());
638}
639
Richard Uhler9b994ea2015-06-24 08:44:19 -0700640// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no
641// OAT file. Expect: The status is kNoDexOptNeeded.
642TEST_F(OatFileAssistantTest, ResourceOnlyDex) {
643 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar";
644
645 Copy(GetStrippedDexSrc1(), dex_location);
646
647 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700648 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700649
Andreas Gampe29d38e72016-03-23 15:31:51 +0000650 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
651 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
652 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
653 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
654 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
655 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700656
657 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000658 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
659 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700660 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
661
662 // Make the oat file up to date. This should have no effect.
663 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700664 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700665 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700666 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700667
Andreas Gampe29d38e72016-03-23 15:31:51 +0000668 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
669 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700670
671 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000672 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
673 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700674 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
675}
676
Richard Uhler66d874d2015-01-15 09:37:19 -0800677// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
678// OAT files both have patch delta of 0.
Richard Uhler5923b522016-12-08 09:48:01 +0000679// Expect: It shouldn't crash.
Richard Uhler66d874d2015-01-15 09:37:19 -0800680TEST_F(OatFileAssistantTest, OdexOatOverlap) {
681 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700682 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex";
683 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -0800684
685 // Create the dex and odex files
686 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000687 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800688
689 // Create the oat file by copying the odex so they are located in the same
690 // place in memory.
691 Copy(odex_location, oat_location);
692
693 // Verify things don't go bad.
694 OatFileAssistant oat_file_assistant(dex_location.c_str(),
Richard Uhlerd1472a22016-04-15 15:18:56 -0700695 oat_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800696
Richard Uhler5923b522016-12-08 09:48:01 +0000697 // kDex2OatForRelocation is expected rather than -kDex2OatForRelocation
Richard Uhler7225a8d2016-11-22 10:12:03 +0000698 // based on the assumption that the oat location is more up-to-date than the odex
Richard Uhler70a84262016-11-08 16:51:51 +0000699 // location, even if they both need relocation.
Richard Uhler5923b522016-12-08 09:48:01 +0000700 EXPECT_EQ(OatFileAssistant::kDex2OatForRelocation,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000701 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800702
703 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000704 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus());
705 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700706 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800707
708 // Things aren't relocated, so it should fall back to interpreted.
709 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
710 ASSERT_TRUE(oat_file.get() != nullptr);
Richard Uhlerf16d5722015-05-11 09:32:47 -0700711
Richard Uhler66d874d2015-01-15 09:37:19 -0800712 EXPECT_FALSE(oat_file->IsExecutable());
713 std::vector<std::unique_ptr<const DexFile>> dex_files;
714 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
715 EXPECT_EQ(1u, dex_files.size());
716}
717
718// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
Richard Uhler95abd042015-03-24 09:51:28 -0700719// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation.
Richard Uhler66d874d2015-01-15 09:37:19 -0800720TEST_F(OatFileAssistantTest, DexPicOdexNoOat) {
721 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -0700722 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -0800723
724 // Create the dex and odex files
725 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000726 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800727
728 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700729 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800730
Andreas Gampe29d38e72016-03-23 15:31:51 +0000731 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
732 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000733 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000734 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything));
Richard Uhler66d874d2015-01-15 09:37:19 -0800735
736 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000737 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000738 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700739 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800740}
741
Andreas Gampe29d38e72016-03-23 15:31:51 +0000742// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file.
743// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code.
744TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) {
745 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar";
746 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex";
David Brazdilce4b0ba2016-01-28 15:05:49 +0000747
748 // Create the dex and odex files
749 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000750 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerifyAtRuntime);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000751
752 // Verify the status.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700753 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
David Brazdilce4b0ba2016-01-28 15:05:49 +0000754
Andreas Gampe29d38e72016-03-23 15:31:51 +0000755 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
756 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime));
Richard Uhler7225a8d2016-11-22 10:12:03 +0000757 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000758 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
David Brazdilce4b0ba2016-01-28 15:05:49 +0000759
760 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler3e580bc2016-11-08 16:23:07 +0000761 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus());
Richard Uhler03bc6592016-11-22 09:42:04 +0000762 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
David Brazdilce4b0ba2016-01-28 15:05:49 +0000763 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles());
764}
765
Richard Uhler66d874d2015-01-15 09:37:19 -0800766// Case: We have a DEX file and up-to-date OAT file for it.
767// Expect: We should load an executable dex file.
768TEST_F(OatFileAssistantTest, LoadOatUpToDate) {
769 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
770
771 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000772 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800773
774 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700775 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000776
777 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
778 ASSERT_TRUE(oat_file.get() != nullptr);
779 EXPECT_TRUE(oat_file->IsExecutable());
780 std::vector<std::unique_ptr<const DexFile>> dex_files;
781 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
782 EXPECT_EQ(1u, dex_files.size());
783}
784
785// Case: We have a DEX file and up-to-date interpret-only OAT file for it.
786// Expect: We should still load the oat file as executable.
787TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) {
788 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar";
789
790 Copy(GetDexSrc1(), dex_location);
791 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kInterpretOnly);
792
793 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700794 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800795
796 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
797 ASSERT_TRUE(oat_file.get() != nullptr);
798 EXPECT_TRUE(oat_file->IsExecutable());
799 std::vector<std::unique_ptr<const DexFile>> dex_files;
800 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
801 EXPECT_EQ(1u, dex_files.size());
802}
803
804// Case: We have a DEX file and up-to-date OAT file for it.
805// Expect: Loading non-executable should load the oat non-executable.
806TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
807 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
808
809 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +0000810 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800811
812 // Load the oat using an oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700813 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800814
815 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
816 ASSERT_TRUE(oat_file.get() != nullptr);
817 EXPECT_FALSE(oat_file->IsExecutable());
818 std::vector<std::unique_ptr<const DexFile>> dex_files;
819 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
820 EXPECT_EQ(1u, dex_files.size());
821}
822
823// Case: We have a DEX file.
824// Expect: We should load an executable dex file from an alternative oat
825// location.
826TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) {
827 std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar";
828 std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat";
829
830 Copy(GetDexSrc1(), dex_location);
831
832 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700833 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800834 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700835 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700836 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700837 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800838
839 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
840 ASSERT_TRUE(oat_file.get() != nullptr);
841 EXPECT_TRUE(oat_file->IsExecutable());
842 std::vector<std::unique_ptr<const DexFile>> dex_files;
843 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
844 EXPECT_EQ(1u, dex_files.size());
845
846 EXPECT_TRUE(OS::FileExists(oat_location.c_str()));
847
848 // Verify it didn't create an oat in the default location.
Richard Uhlerd1472a22016-04-15 15:18:56 -0700849 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler03bc6592016-11-22 09:42:04 +0000850 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800851}
852
Richard Uhler8327cf72015-10-13 16:34:59 -0700853// Case: We have a DEX file but can't write the oat file.
854// Expect: We should fail to make the oat file up to date.
855TEST_F(OatFileAssistantTest, LoadDexUnwriteableAlternateOat) {
856 std::string dex_location = GetScratchDir() + "/LoadDexUnwriteableAlternateOat.jar";
857
858 // Make the oat location unwritable by inserting some non-existent
859 // intermediate directories.
860 std::string oat_location = GetScratchDir() + "/foo/bar/LoadDexUnwriteableAlternateOat.oat";
861
862 Copy(GetDexSrc1(), dex_location);
863
864 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700865 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -0700866 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700867 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700868 ASSERT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700869 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhler8327cf72015-10-13 16:34:59 -0700870
871 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
872 ASSERT_TRUE(oat_file.get() == nullptr);
873}
874
875// Case: We don't have a DEX file and can't write the oat file.
876// Expect: We should fail to generate the oat file without crashing.
877TEST_F(OatFileAssistantTest, GenNoDex) {
878 std::string dex_location = GetScratchDir() + "/GenNoDex.jar";
879 std::string oat_location = GetScratchDir() + "/GenNoDex.oat";
880
881 OatFileAssistant oat_file_assistant(
Richard Uhlerd1472a22016-04-15 15:18:56 -0700882 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
Richard Uhler8327cf72015-10-13 16:34:59 -0700883 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700884 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700885 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerf4b34872016-04-13 11:03:46 -0700886 oat_file_assistant.GenerateOatFile(&error_msg));
Richard Uhler8327cf72015-10-13 16:34:59 -0700887}
888
Richard Uhler66d874d2015-01-15 09:37:19 -0800889// Turn an absolute path into a path relative to the current working
890// directory.
Andreas Gampeca620d72016-11-08 08:09:33 -0800891static std::string MakePathRelative(const std::string& target) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800892 char buf[MAXPATHLEN];
893 std::string cwd = getcwd(buf, MAXPATHLEN);
894
895 // Split the target and cwd paths into components.
896 std::vector<std::string> target_path;
897 std::vector<std::string> cwd_path;
898 Split(target, '/', &target_path);
899 Split(cwd, '/', &cwd_path);
900
901 // Reverse the path components, so we can use pop_back().
902 std::reverse(target_path.begin(), target_path.end());
903 std::reverse(cwd_path.begin(), cwd_path.end());
904
905 // Drop the common prefix of the paths. Because we reversed the path
906 // components, this becomes the common suffix of target_path and cwd_path.
907 while (!target_path.empty() && !cwd_path.empty()
908 && target_path.back() == cwd_path.back()) {
909 target_path.pop_back();
910 cwd_path.pop_back();
911 }
912
913 // For each element of the remaining cwd_path, add '..' to the beginning
914 // of the target path. Because we reversed the path components, we add to
915 // the end of target_path.
916 for (unsigned int i = 0; i < cwd_path.size(); i++) {
917 target_path.push_back("..");
918 }
919
920 // Reverse again to get the right path order, and join to get the result.
921 std::reverse(target_path.begin(), target_path.end());
Andreas Gampe9186ced2016-12-12 14:28:21 -0800922 return android::base::Join(target_path, '/');
Richard Uhler66d874d2015-01-15 09:37:19 -0800923}
924
925// Case: Non-absolute path to Dex location.
926// Expect: Not sure, but it shouldn't crash.
927TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
928 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
929 Copy(GetDexSrc1(), abs_dex_location);
930
931 std::string dex_location = MakePathRelative(abs_dex_location);
Richard Uhlerd1472a22016-04-15 15:18:56 -0700932 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800933
934 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler7225a8d2016-11-22 10:12:03 +0000935 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000936 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +0000937 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
938 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800939}
940
941// Case: Very short, non-existent Dex location.
Richard Uhler9b994ea2015-06-24 08:44:19 -0700942// Expect: kNoDexOptNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800943TEST_F(OatFileAssistantTest, ShortDexLocation) {
944 std::string dex_location = "/xx";
945
Richard Uhlerd1472a22016-04-15 15:18:56 -0700946 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -0800947
948 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Andreas Gampe29d38e72016-03-23 15:31:51 +0000949 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
950 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler03bc6592016-11-22 09:42:04 +0000951 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
952 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler9b994ea2015-06-24 08:44:19 -0700953 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles());
Richard Uhler66d874d2015-01-15 09:37:19 -0800954
Richard Uhler9b994ea2015-06-24 08:44:19 -0700955 // Trying to make it up to date should have no effect.
Richard Uhler66d874d2015-01-15 09:37:19 -0800956 std::string error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700957 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
Richard Uhler1e860612016-03-30 12:17:55 -0700958 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -0700959 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhler9b994ea2015-06-24 08:44:19 -0700960 EXPECT_TRUE(error_msg.empty());
Richard Uhler66d874d2015-01-15 09:37:19 -0800961}
962
963// Case: Non-standard extension for dex file.
Richard Uhler95abd042015-03-24 09:51:28 -0700964// Expect: The status is kDex2OatNeeded.
Richard Uhler66d874d2015-01-15 09:37:19 -0800965TEST_F(OatFileAssistantTest, LongDexExtension) {
966 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
967 Copy(GetDexSrc1(), dex_location);
968
Richard Uhlerd1472a22016-04-15 15:18:56 -0700969 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800970
Richard Uhler7225a8d2016-11-22 10:12:03 +0000971 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch,
Andreas Gampe29d38e72016-03-23 15:31:51 +0000972 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
Richard Uhler66d874d2015-01-15 09:37:19 -0800973
974 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
Richard Uhler03bc6592016-11-22 09:42:04 +0000975 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus());
976 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus());
Richard Uhler66d874d2015-01-15 09:37:19 -0800977}
978
979// A task to generate a dex location. Used by the RaceToGenerate test.
980class RaceGenerateTask : public Task {
981 public:
982 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
Jeff Haof0192c82016-03-28 20:39:50 -0700983 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr)
Richard Uhler66d874d2015-01-15 09:37:19 -0800984 {}
985
Roland Levillain4b8f1ec2015-08-26 18:34:03 +0100986 void Run(Thread* self ATTRIBUTE_UNUSED) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800987 // Load the dex files, and save a pointer to the loaded oat file, so that
988 // we can verify only one oat file was loaded for the dex location.
Richard Uhler66d874d2015-01-15 09:37:19 -0800989 std::vector<std::unique_ptr<const DexFile>> dex_files;
990 std::vector<std::string> error_msgs;
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700991 const OatFile* oat_file = nullptr;
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -0700992 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat(
993 dex_location_.c_str(),
994 oat_location_.c_str(),
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800995 /*class_loader*/nullptr,
996 /*dex_elements*/nullptr,
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700997 &oat_file,
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -0700998 &error_msgs);
Andreas Gampe9186ced2016-12-12 14:28:21 -0800999 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n');
Richard Uhler07b3c232015-03-31 15:57:54 -07001000 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation();
1001 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile();
Mathieu Chartiere58991b2015-10-13 07:59:34 -07001002 CHECK_EQ(loaded_oat_file_, oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001003 }
1004
1005 const OatFile* GetLoadedOatFile() const {
1006 return loaded_oat_file_;
1007 }
1008
1009 private:
1010 std::string dex_location_;
1011 std::string oat_location_;
1012 const OatFile* loaded_oat_file_;
1013};
1014
1015// Test the case where multiple processes race to generate an oat file.
1016// This simulates multiple processes using multiple threads.
1017//
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001018// We want unique Oat files to be loaded even when there is a race to load.
1019// TODO: The test case no longer tests locking the way it was intended since we now get multiple
1020// copies of the same Oat files mapped at different locations.
Richard Uhler66d874d2015-01-15 09:37:19 -08001021TEST_F(OatFileAssistantTest, RaceToGenerate) {
1022 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001023 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat";
Richard Uhler66d874d2015-01-15 09:37:19 -08001024
1025 // We use the lib core dex file, because it's large, and hopefully should
1026 // take a while to generate.
Narayan Kamathd1ef4362015-11-12 11:49:06 +00001027 Copy(GetLibCoreDexFileNames()[0], dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -08001028
1029 const int kNumThreads = 32;
1030 Thread* self = Thread::Current();
1031 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
1032 std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
1033 for (int i = 0; i < kNumThreads; i++) {
1034 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
1035 thread_pool.AddTask(self, task.get());
1036 tasks.push_back(std::move(task));
1037 }
1038 thread_pool.StartWorkers(self);
1039 thread_pool.Wait(self, true, false);
1040
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001041 // Verify every task got a unique oat file.
1042 std::set<const OatFile*> oat_files;
Richard Uhler66d874d2015-01-15 09:37:19 -08001043 for (auto& task : tasks) {
Mathieu Chartierf9c6fc62015-10-07 11:44:05 -07001044 const OatFile* oat_file = task->GetLoadedOatFile();
1045 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end());
1046 oat_files.insert(oat_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001047 }
1048}
1049
1050// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
1051// disabled.
1052// Expect: We should load the odex file non-executable.
1053TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
1054 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001055 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001056
1057 // Create the dex and odex files
1058 Copy(GetDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001059 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001060
1061 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001062 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001063
1064 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1065 ASSERT_TRUE(oat_file.get() != nullptr);
1066 EXPECT_FALSE(oat_file->IsExecutable());
1067 std::vector<std::unique_ptr<const DexFile>> dex_files;
1068 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1069 EXPECT_EQ(1u, dex_files.size());
1070}
1071
1072// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
1073// disabled.
1074// Expect: We should load the odex file non-executable.
1075TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
1076 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
Richard Uhler63434112015-03-16 14:32:16 -07001077 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex";
Richard Uhler66d874d2015-01-15 09:37:19 -08001078
1079 // Create the dex and odex files
1080 Copy(GetMultiDexSrc1(), dex_location);
Andreas Gampe29d38e72016-03-23 15:31:51 +00001081 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed);
Richard Uhler66d874d2015-01-15 09:37:19 -08001082
1083 // Load the oat using an executable oat file assistant.
Richard Uhlerd1472a22016-04-15 15:18:56 -07001084 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
Richard Uhler66d874d2015-01-15 09:37:19 -08001085
1086 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
1087 ASSERT_TRUE(oat_file.get() != nullptr);
1088 EXPECT_FALSE(oat_file->IsExecutable());
1089 std::vector<std::unique_ptr<const DexFile>> dex_files;
1090 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
1091 EXPECT_EQ(2u, dex_files.size());
1092}
1093
Richard Uhlerf4b34872016-04-13 11:03:46 -07001094TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) {
1095 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar";
1096 Copy(GetDexSrc1(), dex_location);
1097
Richard Uhlerd1472a22016-04-15 15:18:56 -07001098 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
Richard Uhlerf4b34872016-04-13 11:03:46 -07001099
1100 std::string error_msg;
1101 Runtime::Current()->AddCompilerOption("--compiler-filter=interpret-only");
1102 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001103 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001104 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1105 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
Richard Uhler7225a8d2016-11-22 10:12:03 +00001106 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter,
Richard Uhlerf4b34872016-04-13 11:03:46 -07001107 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1108
1109 Runtime::Current()->AddCompilerOption("--compiler-filter=speed");
1110 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001111 oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg;
Richard Uhlerf4b34872016-04-13 11:03:46 -07001112 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1113 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly));
1114 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded,
1115 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed));
1116
1117 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus");
1118 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted,
Richard Uhlerd1472a22016-04-15 15:18:56 -07001119 oat_file_assistant.MakeUpToDate(false, &error_msg));
Richard Uhlerf4b34872016-04-13 11:03:46 -07001120}
1121
Richard Uhlerb81881d2016-04-19 13:08:04 -07001122TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) {
Richard Uhler66d874d2015-01-15 09:37:19 -08001123 std::string error_msg;
1124 std::string odex_file;
1125
Richard Uhlerb81881d2016-04-19 13:08:04 -07001126 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001127 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001128 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001129
Richard Uhlerb81881d2016-04-19 13:08:04 -07001130 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001131 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg;
Richard Uhler63434112015-03-16 14:32:16 -07001132 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file);
Richard Uhler66d874d2015-01-15 09:37:19 -08001133
Richard Uhlerb81881d2016-04-19 13:08:04 -07001134 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001135 "nopath.jar", kArm, &odex_file, &error_msg));
Richard Uhlerb81881d2016-04-19 13:08:04 -07001136 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -07001137 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -08001138}
1139
Richard Uhler23cedd22015-04-08 13:17:29 -07001140// Verify the dexopt status values from dalvik.system.DexFile
1141// match the OatFileAssistant::DexOptStatus values.
1142TEST_F(OatFileAssistantTest, DexOptStatusValues) {
Richard Uhler7225a8d2016-11-22 10:12:03 +00001143 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = {
1144 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"},
1145 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"},
1146 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"},
1147 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"},
1148 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"},
Richard Uhler7225a8d2016-11-22 10:12:03 +00001149 };
1150
Richard Uhler23cedd22015-04-08 13:17:29 -07001151 ScopedObjectAccess soa(Thread::Current());
1152 StackHandleScope<1> hs(soa.Self());
1153 ClassLinker* linker = Runtime::Current()->GetClassLinker();
1154 Handle<mirror::Class> dexfile(
1155 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;")));
1156 ASSERT_FALSE(dexfile.Get() == nullptr);
1157 linker->EnsureInitialized(soa.Self(), dexfile, true, true);
1158
Richard Uhler7225a8d2016-11-22 10:12:03 +00001159 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
1160 ArtField* art_field = mirror::Class::FindStaticField(
Vladimir Marko19a4d372016-12-08 14:41:46 +00001161 soa.Self(), dexfile.Get(), field.second, "I");
Richard Uhler7225a8d2016-11-22 10:12:03 +00001162 ASSERT_FALSE(art_field == nullptr);
1163 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
1164 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
1165 }
Richard Uhler23cedd22015-04-08 13:17:29 -07001166}
Richard Uhler66d874d2015-01-15 09:37:19 -08001167
1168// TODO: More Tests:
1169// * Test class linker falls back to unquickened dex for DexNoOat
1170// * Test class linker falls back to unquickened dex for MultiDexNoOat
Richard Uhler66d874d2015-01-15 09:37:19 -08001171// * Test using secondary isa
Richard Uhler66d874d2015-01-15 09:37:19 -08001172// * Test for status of oat while oat is being generated (how?)
1173// * Test case where 32 and 64 bit boot class paths differ,
1174// and we ask IsInBootClassPath for a class in exactly one of the 32 or
1175// 64 bit boot class paths.
1176// * Test unexpected scenarios (?):
1177// - Dex is stripped, don't have odex.
1178// - Oat file corrupted after status check, before reload unexecutable
1179// because it's unrelocated and no dex2oat
Calin Juravleb077e152016-02-18 18:47:37 +00001180// * Test unrelocated specific target compilation type can be relocated to
1181// make it up to date.
Richard Uhler66d874d2015-01-15 09:37:19 -08001182} // namespace art