1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <algorithm> 18#include <fstream> 19#include <string> 20#include <vector> 21#include <sys/param.h> 22 23#include <backtrace/BacktraceMap.h> 24#include <gtest/gtest.h> 25 26#include "art_field-inl.h" 27#include "class_linker-inl.h" 28#include "common_runtime_test.h" 29#include "compiler_callbacks.h" 30#include "dex2oat_environment_test.h" 31#include "gc/space/image_space.h" 32#include "mem_map.h" 33#include "oat_file_assistant.h" 34#include "oat_file_manager.h" 35#include "os.h" 36#include "scoped_thread_state_change.h" 37#include "thread-inl.h" 38#include "utils.h" 39 40namespace art { 41 42class OatFileAssistantTest : public Dex2oatEnvironmentTest { 43 public: 44 virtual void SetUp() OVERRIDE { 45 ReserveImageSpace(); 46 Dex2oatEnvironmentTest::SetUp(); 47 } 48 49 // Pre-Relocate the image to a known non-zero offset so we don't have to 50 // deal with the runtime randomly relocating the image by 0 and messing up 51 // the expected results of the tests. 52 bool PreRelocateImage(std::string* error_msg) { 53 std::string image; 54 if (!GetCachedImageFile(&image, error_msg)) { 55 return false; 56 } 57 58 std::string patchoat = GetAndroidRoot(); 59 patchoat += kIsDebugBuild ? "/bin/patchoatd" : "/bin/patchoat"; 60 61 std::vector<std::string> argv; 62 argv.push_back(patchoat); 63 argv.push_back("--input-image-location=" + GetImageLocation()); 64 argv.push_back("--output-image-file=" + image); 65 argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(kRuntimeISA))); 66 argv.push_back("--base-offset-delta=0x00008000"); 67 return Exec(argv, error_msg); 68 } 69 70 virtual void PreRuntimeCreate() { 71 std::string error_msg; 72 ASSERT_TRUE(PreRelocateImage(&error_msg)) << error_msg; 73 74 UnreserveImageSpace(); 75 } 76 77 virtual void PostRuntimeCreate() OVERRIDE { 78 ReserveImageSpace(); 79 } 80 81 // Generate a non-PIC odex file for the purposes of test. 82 // The generated odex file will be un-relocated. 83 void GenerateOdexForTest(const std::string& dex_location, 84 const std::string& odex_location, 85 CompilerFilter::Filter filter, 86 bool pic = false, 87 bool with_patch_info = true) { 88 // Temporarily redirect the dalvik cache so dex2oat doesn't find the 89 // relocated image file. 90 std::string dalvik_cache = GetDalvikCache(GetInstructionSetString(kRuntimeISA)); 91 std::string dalvik_cache_tmp = dalvik_cache + ".redirected"; 92 ASSERT_EQ(0, rename(dalvik_cache.c_str(), dalvik_cache_tmp.c_str())) << strerror(errno); 93 94 std::vector<std::string> args; 95 args.push_back("--dex-file=" + dex_location); 96 args.push_back("--oat-file=" + odex_location); 97 args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter)); 98 args.push_back("--runtime-arg"); 99 args.push_back("-Xnorelocate"); 100 101 if (pic) { 102 args.push_back("--compile-pic"); 103 } 104 105 if (with_patch_info) { 106 args.push_back("--include-patch-information"); 107 } 108 109 std::string error_msg; 110 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg; 111 ASSERT_EQ(0, rename(dalvik_cache_tmp.c_str(), dalvik_cache.c_str())) << strerror(errno); 112 113 // Verify the odex file was generated as expected and really is 114 // unrelocated. 115 std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(), 116 odex_location.c_str(), 117 nullptr, 118 nullptr, 119 false, 120 /*low_4gb*/false, 121 dex_location.c_str(), 122 &error_msg)); 123 ASSERT_TRUE(odex_file.get() != nullptr) << error_msg; 124 EXPECT_EQ(pic, odex_file->IsPic()); 125 EXPECT_EQ(with_patch_info, odex_file->HasPatchInfo()); 126 EXPECT_EQ(filter, odex_file->GetCompilerFilter()); 127 128 if (CompilerFilter::IsBytecodeCompilationEnabled(filter)) { 129 const std::vector<gc::space::ImageSpace*> image_spaces = 130 Runtime::Current()->GetHeap()->GetBootImageSpaces(); 131 ASSERT_TRUE(!image_spaces.empty() && image_spaces[0] != nullptr); 132 const ImageHeader& image_header = image_spaces[0]->GetImageHeader(); 133 const OatHeader& oat_header = odex_file->GetOatHeader(); 134 uint32_t combined_checksum = OatFileAssistant::CalculateCombinedImageChecksum(); 135 EXPECT_EQ(combined_checksum, oat_header.GetImageFileLocationOatChecksum()); 136 EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()), 137 oat_header.GetImageFileLocationOatDataBegin()); 138 EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta()); 139 } 140 } 141 142 void GeneratePicOdexForTest(const std::string& dex_location, 143 const std::string& odex_location, 144 CompilerFilter::Filter filter) { 145 GenerateOdexForTest(dex_location, odex_location, filter, true, false); 146 } 147 148 // Generate a non-PIC odex file without patch information for the purposes 149 // of test. The generated odex file will be un-relocated. 150 void GenerateNoPatchOdexForTest(const std::string& dex_location, 151 const std::string& odex_location, 152 CompilerFilter::Filter filter) { 153 GenerateOdexForTest(dex_location, odex_location, filter, false, false); 154 } 155 156 private: 157 // Reserve memory around where the image will be loaded so other memory 158 // won't conflict when it comes time to load the image. 159 // This can be called with an already loaded image to reserve the space 160 // around it. 161 void ReserveImageSpace() { 162 MemMap::Init(); 163 164 // Ensure a chunk of memory is reserved for the image space. 165 // The reservation_end includes room for the main space that has to come 166 // right after the image in case of the GSS collector. 167 uintptr_t reservation_start = ART_BASE_ADDRESS; 168 uintptr_t reservation_end = ART_BASE_ADDRESS + 384 * MB; 169 170 std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true)); 171 ASSERT_TRUE(map.get() != nullptr) << "Failed to build process map"; 172 for (BacktraceMap::const_iterator it = map->begin(); 173 reservation_start < reservation_end && it != map->end(); ++it) { 174 ReserveImageSpaceChunk(reservation_start, std::min(it->start, reservation_end)); 175 reservation_start = std::max(reservation_start, it->end); 176 } 177 ReserveImageSpaceChunk(reservation_start, reservation_end); 178 } 179 180 // Reserve a chunk of memory for the image space in the given range. 181 // Only has effect for chunks with a positive number of bytes. 182 void ReserveImageSpaceChunk(uintptr_t start, uintptr_t end) { 183 if (start < end) { 184 std::string error_msg; 185 image_reservation_.push_back(std::unique_ptr<MemMap>( 186 MemMap::MapAnonymous("image reservation", 187 reinterpret_cast<uint8_t*>(start), end - start, 188 PROT_NONE, false, false, &error_msg))); 189 ASSERT_TRUE(image_reservation_.back().get() != nullptr) << error_msg; 190 LOG(INFO) << "Reserved space for image " << 191 reinterpret_cast<void*>(image_reservation_.back()->Begin()) << "-" << 192 reinterpret_cast<void*>(image_reservation_.back()->End()); 193 } 194 } 195 196 197 // Unreserve any memory reserved by ReserveImageSpace. This should be called 198 // before the image is loaded. 199 void UnreserveImageSpace() { 200 image_reservation_.clear(); 201 } 202 203 std::vector<std::unique_ptr<MemMap>> image_reservation_; 204}; 205 206class OatFileAssistantNoDex2OatTest : public OatFileAssistantTest { 207 public: 208 virtual void SetUpRuntimeOptions(RuntimeOptions* options) { 209 OatFileAssistantTest::SetUpRuntimeOptions(options); 210 options->push_back(std::make_pair("-Xnodex2oat", nullptr)); 211 } 212}; 213 214// Generate an oat file for the purposes of test, as opposed to testing 215// generation of oat files. 216static void GenerateOatForTest(const char* dex_location, CompilerFilter::Filter filter) { 217 // Use an oat file assistant to find the proper oat location. 218 OatFileAssistant ofa(dex_location, kRuntimeISA, false, false); 219 const std::string* oat_location = ofa.OatFileName(); 220 ASSERT_TRUE(oat_location != nullptr); 221 222 std::vector<std::string> args; 223 args.push_back("--dex-file=" + std::string(dex_location)); 224 args.push_back("--oat-file=" + *oat_location); 225 args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter)); 226 args.push_back("--runtime-arg"); 227 args.push_back("-Xnorelocate"); 228 std::string error_msg; 229 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg; 230 231 // Verify the oat file was generated as expected. 232 std::unique_ptr<OatFile> oat_file(OatFile::Open(oat_location->c_str(), 233 oat_location->c_str(), 234 nullptr, 235 nullptr, 236 false, 237 /*low_4gb*/false, 238 dex_location, 239 &error_msg)); 240 ASSERT_TRUE(oat_file.get() != nullptr) << error_msg; 241 EXPECT_EQ(filter, oat_file->GetCompilerFilter()); 242} 243 244// Case: We have a DEX file, but no OAT file for it. 245// Expect: The status is kDex2OatNeeded. 246TEST_F(OatFileAssistantTest, DexNoOat) { 247 std::string dex_location = GetScratchDir() + "/DexNoOat.jar"; 248 Copy(GetDexSrc1(), dex_location); 249 250 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 251 252 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 253 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); 254 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 255 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); 256 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 257 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile)); 258 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 259 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 260 261 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 262 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 263 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 264 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 265 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 266 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OdexFileStatus()); 267 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 268 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 269 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 270 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 271 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OatFileStatus()); 272 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 273} 274 275// Case: We have no DEX file and no OAT file. 276// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash. 277TEST_F(OatFileAssistantTest, NoDexNoOat) { 278 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar"; 279 280 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 281 282 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 283 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 284 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 285 286 // Trying to make the oat file up to date should not fail or crash. 287 std::string error_msg; 288 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 289 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)); 290 291 // Trying to get the best oat file should fail, but not crash. 292 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 293 EXPECT_EQ(nullptr, oat_file.get()); 294} 295 296// Case: We have a DEX file and up-to-date OAT file for it. 297// Expect: The status is kNoDexOptNeeded. 298TEST_F(OatFileAssistantTest, OatUpToDate) { 299 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar"; 300 Copy(GetDexSrc1(), dex_location); 301 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 302 303 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 304 305 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 306 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 307 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 308 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); 309 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 310 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); 311 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 312 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 313 314 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 315 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 316 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 317 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 318 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 319 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 320 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 321 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 322 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus()); 323 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 324} 325 326// Case: We have a DEX file and speed-profile OAT file for it. 327// Expect: The status is kNoDexOptNeeded if the profile hasn't changed. 328TEST_F(OatFileAssistantTest, ProfileOatUpToDate) { 329 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar"; 330 Copy(GetDexSrc1(), dex_location); 331 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile); 332 333 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 334 335 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 336 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile)); 337 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 338 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); 339 340 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 341 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 342 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 343 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 344 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 345 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 346 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 347 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 348 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus()); 349 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 350} 351 352// Case: We have a DEX file and speed-profile OAT file for it. 353// Expect: The status is kNoDex2OatNeeded if the profile has changed. 354TEST_F(OatFileAssistantTest, ProfileOatOutOfDate) { 355 std::string dex_location = GetScratchDir() + "/ProfileOatOutOfDate.jar"; 356 Copy(GetDexSrc1(), dex_location); 357 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile); 358 359 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true, false); 360 361 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 362 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile)); 363 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 364 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); 365 366 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 367 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 368 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 369 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 370 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 371 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 372 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 373 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 374 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OatFileStatus()); 375 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 376} 377 378// Case: We have a MultiDEX file and up-to-date OAT file for it. 379// Expect: The status is kNoDexOptNeeded and we load all dex files. 380TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) { 381 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar"; 382 Copy(GetMultiDexSrc1(), dex_location); 383 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 384 385 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 386 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 387 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 388 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 389 390 // Verify we can load both dex files. 391 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 392 ASSERT_TRUE(oat_file.get() != nullptr); 393 EXPECT_TRUE(oat_file->IsExecutable()); 394 std::vector<std::unique_ptr<const DexFile>> dex_files; 395 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 396 EXPECT_EQ(2u, dex_files.size()); 397} 398 399// Case: We have a MultiDEX file where the secondary dex file is out of date. 400// Expect: The status is kDex2OatNeeded. 401TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) { 402 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar"; 403 404 // Compile code for GetMultiDexSrc1. 405 Copy(GetMultiDexSrc1(), dex_location); 406 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 407 408 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum 409 // is out of date. 410 Copy(GetMultiDexSrc2(), dex_location); 411 412 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 413 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 414 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 415 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 416} 417 418// Case: We have a MultiDEX file and up-to-date OAT file for it with relative 419// encoded dex locations. 420// Expect: The oat file status is kNoDexOptNeeded. 421TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) { 422 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar"; 423 std::string oat_location = GetOdexDir() + "/RelativeEncodedDexLocation.oat"; 424 425 // Create the dex file 426 Copy(GetMultiDexSrc1(), dex_location); 427 428 // Create the oat file with relative encoded dex location. 429 std::vector<std::string> args; 430 args.push_back("--dex-file=" + dex_location); 431 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar")); 432 args.push_back("--oat-file=" + oat_location); 433 args.push_back("--compiler-filter=speed"); 434 435 std::string error_msg; 436 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg; 437 438 // Verify we can load both dex files. 439 OatFileAssistant oat_file_assistant(dex_location.c_str(), 440 oat_location.c_str(), 441 kRuntimeISA, false, true); 442 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 443 ASSERT_TRUE(oat_file.get() != nullptr); 444 EXPECT_TRUE(oat_file->IsExecutable()); 445 std::vector<std::unique_ptr<const DexFile>> dex_files; 446 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 447 EXPECT_EQ(2u, dex_files.size()); 448} 449 450// Case: We have a DEX file and out-of-date OAT file. 451// Expect: The status is kDex2OatNeeded. 452TEST_F(OatFileAssistantTest, OatOutOfDate) { 453 std::string dex_location = GetScratchDir() + "/OatOutOfDate.jar"; 454 455 // We create a dex, generate an oat for it, then overwrite the dex with a 456 // different dex to make the oat out of date. 457 Copy(GetDexSrc1(), dex_location); 458 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 459 Copy(GetDexSrc2(), dex_location); 460 461 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 462 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 463 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); 464 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 465 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 466 467 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 468 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 469 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 470 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 471 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 472 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 473 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 474 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 475} 476 477// Case: We have a DEX file and an ODEX file, but no OAT file. 478// Expect: The status is kPatchOatNeeded. 479TEST_F(OatFileAssistantTest, DexOdexNoOat) { 480 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar"; 481 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex"; 482 483 // Create the dex and odex files 484 Copy(GetDexSrc1(), dex_location); 485 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 486 487 // Verify the status. 488 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 489 490 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 491 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); 492 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, 493 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 494 495 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 496 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 497 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 498 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 499 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation()); 500 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 501 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 502 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 503 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 504 505 // We should still be able to get the non-executable odex file to run from. 506 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 507 ASSERT_TRUE(oat_file.get() != nullptr); 508} 509 510// Case: We have a stripped DEX file and an ODEX file, but no OAT file. 511// Expect: The status is kPatchOatNeeded 512TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) { 513 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar"; 514 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex"; 515 516 // Create the dex and odex files 517 Copy(GetDexSrc1(), dex_location); 518 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 519 520 // Strip the dex file 521 Copy(GetStrippedDexSrc1(), dex_location); 522 523 // Verify the status. 524 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 525 526 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, 527 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 528 529 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 530 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 531 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 532 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 533 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 534 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 535 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 536 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 537 538 // Make the oat file up to date. 539 std::string error_msg; 540 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded, 541 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg; 542 543 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 544 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 545 546 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 547 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 548 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 549 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 550 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 551 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 552 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 553 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 554 555 // Verify we can load the dex files from it. 556 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 557 ASSERT_TRUE(oat_file.get() != nullptr); 558 EXPECT_TRUE(oat_file->IsExecutable()); 559 std::vector<std::unique_ptr<const DexFile>> dex_files; 560 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 561 EXPECT_EQ(1u, dex_files.size()); 562} 563 564// Case: We have a stripped DEX file, an ODEX file, and an out-of-date OAT file. 565// Expect: The status is kPatchOatNeeded. 566TEST_F(OatFileAssistantTest, StrippedDexOdexOat) { 567 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar"; 568 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex"; 569 570 // Create the oat file from a different dex file so it looks out of date. 571 Copy(GetDexSrc2(), dex_location); 572 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 573 574 // Create the odex file 575 Copy(GetDexSrc1(), dex_location); 576 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 577 578 // Strip the dex file. 579 Copy(GetStrippedDexSrc1(), dex_location); 580 581 // Verify the status. 582 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 583 584 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 585 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); 586 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, 587 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 588 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, // Can't run dex2oat because dex file is stripped. 589 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 590 591 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 592 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 593 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 594 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation()); 595 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 596 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 597 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 598 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 599 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 600 601 // Make the oat file up to date. 602 std::string error_msg; 603 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded, 604 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg; 605 606 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 607 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 608 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, // Can't run dex2oat because dex file is stripped. 609 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 610 611 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 612 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 613 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 614 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation()); 615 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 616 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 617 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 618 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 619 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 620 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 621 622 // Verify we can load the dex files from it. 623 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 624 ASSERT_TRUE(oat_file.get() != nullptr); 625 EXPECT_TRUE(oat_file->IsExecutable()); 626 std::vector<std::unique_ptr<const DexFile>> dex_files; 627 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 628 EXPECT_EQ(1u, dex_files.size()); 629} 630 631// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no 632// OAT file. Expect: The status is kNoDexOptNeeded. 633TEST_F(OatFileAssistantTest, ResourceOnlyDex) { 634 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar"; 635 636 Copy(GetStrippedDexSrc1(), dex_location); 637 638 // Verify the status. 639 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 640 641 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 642 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 643 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 644 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); 645 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 646 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); 647 648 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 649 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 650 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 651 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 652 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 653 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 654 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 655 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 656 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 657 658 // Make the oat file up to date. This should have no effect. 659 std::string error_msg; 660 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 661 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg; 662 663 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 664 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 665 666 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 667 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 668 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 669 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 670 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 671 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 672 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 673 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 674 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 675} 676 677// Case: We have a DEX file, no ODEX file and an OAT file that needs 678// relocation. 679// Expect: The status is kSelfPatchOatNeeded. 680TEST_F(OatFileAssistantTest, SelfRelocation) { 681 std::string dex_location = GetScratchDir() + "/SelfRelocation.jar"; 682 std::string oat_location = GetOdexDir() + "/SelfRelocation.oat"; 683 684 // Create the dex and odex files 685 Copy(GetDexSrc1(), dex_location); 686 GenerateOdexForTest(dex_location, oat_location, CompilerFilter::kSpeed); 687 688 OatFileAssistant oat_file_assistant(dex_location.c_str(), 689 oat_location.c_str(), kRuntimeISA, false, true); 690 691 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 692 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); 693 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, 694 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 695 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 696 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 697 698 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 699 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 700 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 701 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 702 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 703 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 704 EXPECT_TRUE(oat_file_assistant.OatFileNeedsRelocation()); 705 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 706 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 707 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 708 709 // Make the oat file up to date. 710 std::string error_msg; 711 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded, 712 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg; 713 714 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 715 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 716 717 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 718 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 719 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 720 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 721 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 722 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 723 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 724 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 725 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 726 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 727 728 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 729 ASSERT_TRUE(oat_file.get() != nullptr); 730 EXPECT_TRUE(oat_file->IsExecutable()); 731 std::vector<std::unique_ptr<const DexFile>> dex_files; 732 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 733 EXPECT_EQ(1u, dex_files.size()); 734} 735 736// Case: We have a DEX file, no ODEX file and an OAT file that needs 737// relocation but doesn't have patch info. 738// Expect: The status is kDex2OatNeeded, because we can't run patchoat. 739TEST_F(OatFileAssistantTest, NoSelfRelocation) { 740 std::string dex_location = GetScratchDir() + "/NoSelfRelocation.jar"; 741 std::string oat_location = GetOdexDir() + "/NoSelfRelocation.oat"; 742 743 // Create the dex and odex files 744 Copy(GetDexSrc1(), dex_location); 745 GenerateNoPatchOdexForTest(dex_location, oat_location, CompilerFilter::kSpeed); 746 747 OatFileAssistant oat_file_assistant(dex_location.c_str(), 748 oat_location.c_str(), kRuntimeISA, false, true); 749 750 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 751 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 752 753 // Make the oat file up to date. 754 std::string error_msg; 755 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded, 756 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg; 757 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 758 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 759 760 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 761 ASSERT_TRUE(oat_file.get() != nullptr); 762 EXPECT_TRUE(oat_file->IsExecutable()); 763 std::vector<std::unique_ptr<const DexFile>> dex_files; 764 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 765 EXPECT_EQ(1u, dex_files.size()); 766} 767 768// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and 769// OAT files both have patch delta of 0. 770// Expect: It shouldn't crash, and status is kPatchOatNeeded. 771TEST_F(OatFileAssistantTest, OdexOatOverlap) { 772 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar"; 773 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex"; 774 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat"; 775 776 // Create the dex and odex files 777 Copy(GetDexSrc1(), dex_location); 778 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 779 780 // Create the oat file by copying the odex so they are located in the same 781 // place in memory. 782 Copy(odex_location, oat_location); 783 784 // Verify things don't go bad. 785 OatFileAssistant oat_file_assistant(dex_location.c_str(), 786 oat_location.c_str(), kRuntimeISA, false, true); 787 788 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, 789 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 790 791 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 792 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 793 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 794 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 795 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 796 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 797 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 798 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 799 800 // Things aren't relocated, so it should fall back to interpreted. 801 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 802 ASSERT_TRUE(oat_file.get() != nullptr); 803 804 EXPECT_FALSE(oat_file->IsExecutable()); 805 std::vector<std::unique_ptr<const DexFile>> dex_files; 806 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 807 EXPECT_EQ(1u, dex_files.size()); 808} 809 810// Case: We have a DEX file and a PIC ODEX file, but no OAT file. 811// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation. 812TEST_F(OatFileAssistantTest, DexPicOdexNoOat) { 813 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar"; 814 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex"; 815 816 // Create the dex and odex files 817 Copy(GetDexSrc1(), dex_location); 818 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 819 820 // Verify the status. 821 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 822 823 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 824 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 825 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 826 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 827 828 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 829 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 830 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 831 EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate()); 832 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 833 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 834 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 835 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 836} 837 838// Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file. 839// Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code. 840TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) { 841 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar"; 842 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex"; 843 844 // Create the dex and odex files 845 Copy(GetDexSrc1(), dex_location); 846 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerifyAtRuntime); 847 848 // Verify the status. 849 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 850 851 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 852 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); 853 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 854 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 855 856 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 857 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 858 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 859 EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate()); 860 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 861 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 862 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 863 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 864} 865 866// Case: We have a DEX file and up-to-date OAT file for it. 867// Expect: We should load an executable dex file. 868TEST_F(OatFileAssistantTest, LoadOatUpToDate) { 869 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar"; 870 871 Copy(GetDexSrc1(), dex_location); 872 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 873 874 // Load the oat using an oat file assistant. 875 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 876 877 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 878 ASSERT_TRUE(oat_file.get() != nullptr); 879 EXPECT_TRUE(oat_file->IsExecutable()); 880 std::vector<std::unique_ptr<const DexFile>> dex_files; 881 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 882 EXPECT_EQ(1u, dex_files.size()); 883} 884 885// Case: We have a DEX file and up-to-date interpret-only OAT file for it. 886// Expect: We should still load the oat file as executable. 887TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) { 888 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar"; 889 890 Copy(GetDexSrc1(), dex_location); 891 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kInterpretOnly); 892 893 // Load the oat using an oat file assistant. 894 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 895 896 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 897 ASSERT_TRUE(oat_file.get() != nullptr); 898 EXPECT_TRUE(oat_file->IsExecutable()); 899 std::vector<std::unique_ptr<const DexFile>> dex_files; 900 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 901 EXPECT_EQ(1u, dex_files.size()); 902} 903 904// Case: We have a DEX file and up-to-date OAT file for it. 905// Expect: Loading non-executable should load the oat non-executable. 906TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) { 907 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar"; 908 909 Copy(GetDexSrc1(), dex_location); 910 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 911 912 // Load the oat using an oat file assistant. 913 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 914 915 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 916 ASSERT_TRUE(oat_file.get() != nullptr); 917 EXPECT_FALSE(oat_file->IsExecutable()); 918 std::vector<std::unique_ptr<const DexFile>> dex_files; 919 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 920 EXPECT_EQ(1u, dex_files.size()); 921} 922 923// Case: We have a DEX file. 924// Expect: We should load an executable dex file from an alternative oat 925// location. 926TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) { 927 std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar"; 928 std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat"; 929 930 Copy(GetDexSrc1(), dex_location); 931 932 OatFileAssistant oat_file_assistant( 933 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true); 934 std::string error_msg; 935 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded, 936 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)) << error_msg; 937 938 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 939 ASSERT_TRUE(oat_file.get() != nullptr); 940 EXPECT_TRUE(oat_file->IsExecutable()); 941 std::vector<std::unique_ptr<const DexFile>> dex_files; 942 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 943 EXPECT_EQ(1u, dex_files.size()); 944 945 EXPECT_TRUE(OS::FileExists(oat_location.c_str())); 946 947 // Verify it didn't create an oat in the default location. 948 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false, false); 949 EXPECT_FALSE(ofm.OatFileExists()); 950} 951 952// Case: We have a DEX file but can't write the oat file. 953// Expect: We should fail to make the oat file up to date. 954TEST_F(OatFileAssistantTest, LoadDexUnwriteableAlternateOat) { 955 std::string dex_location = GetScratchDir() + "/LoadDexUnwriteableAlternateOat.jar"; 956 957 // Make the oat location unwritable by inserting some non-existent 958 // intermediate directories. 959 std::string oat_location = GetScratchDir() + "/foo/bar/LoadDexUnwriteableAlternateOat.oat"; 960 961 Copy(GetDexSrc1(), dex_location); 962 963 OatFileAssistant oat_file_assistant( 964 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true); 965 std::string error_msg; 966 ASSERT_EQ(OatFileAssistant::kUpdateNotAttempted, 967 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)); 968 969 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 970 ASSERT_TRUE(oat_file.get() == nullptr); 971} 972 973// Case: We don't have a DEX file and can't write the oat file. 974// Expect: We should fail to generate the oat file without crashing. 975TEST_F(OatFileAssistantTest, GenNoDex) { 976 std::string dex_location = GetScratchDir() + "/GenNoDex.jar"; 977 std::string oat_location = GetScratchDir() + "/GenNoDex.oat"; 978 979 OatFileAssistant oat_file_assistant( 980 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, false, true); 981 std::string error_msg; 982 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted, 983 oat_file_assistant.GenerateOatFile(CompilerFilter::kSpeed, &error_msg)); 984} 985 986// Turn an absolute path into a path relative to the current working 987// directory. 988static std::string MakePathRelative(std::string target) { 989 char buf[MAXPATHLEN]; 990 std::string cwd = getcwd(buf, MAXPATHLEN); 991 992 // Split the target and cwd paths into components. 993 std::vector<std::string> target_path; 994 std::vector<std::string> cwd_path; 995 Split(target, '/', &target_path); 996 Split(cwd, '/', &cwd_path); 997 998 // Reverse the path components, so we can use pop_back(). 999 std::reverse(target_path.begin(), target_path.end()); 1000 std::reverse(cwd_path.begin(), cwd_path.end()); 1001 1002 // Drop the common prefix of the paths. Because we reversed the path 1003 // components, this becomes the common suffix of target_path and cwd_path. 1004 while (!target_path.empty() && !cwd_path.empty() 1005 && target_path.back() == cwd_path.back()) { 1006 target_path.pop_back(); 1007 cwd_path.pop_back(); 1008 } 1009 1010 // For each element of the remaining cwd_path, add '..' to the beginning 1011 // of the target path. Because we reversed the path components, we add to 1012 // the end of target_path. 1013 for (unsigned int i = 0; i < cwd_path.size(); i++) { 1014 target_path.push_back(".."); 1015 } 1016 1017 // Reverse again to get the right path order, and join to get the result. 1018 std::reverse(target_path.begin(), target_path.end()); 1019 return Join(target_path, '/'); 1020} 1021 1022// Case: Non-absolute path to Dex location. 1023// Expect: Not sure, but it shouldn't crash. 1024TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) { 1025 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar"; 1026 Copy(GetDexSrc1(), abs_dex_location); 1027 1028 std::string dex_location = MakePathRelative(abs_dex_location); 1029 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 1030 1031 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 1032 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 1033 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 1034 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 1035 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 1036 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 1037 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 1038 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 1039 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 1040} 1041 1042// Case: Very short, non-existent Dex location. 1043// Expect: kNoDexOptNeeded. 1044TEST_F(OatFileAssistantTest, ShortDexLocation) { 1045 std::string dex_location = "/xx"; 1046 1047 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 1048 1049 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 1050 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 1051 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 1052 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 1053 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 1054 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 1055 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 1056 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 1057 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 1058 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 1059 1060 // Trying to make it up to date should have no effect. 1061 std::string error_msg; 1062 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 1063 oat_file_assistant.MakeUpToDate(CompilerFilter::kSpeed, &error_msg)); 1064 EXPECT_TRUE(error_msg.empty()); 1065} 1066 1067// Case: Non-standard extension for dex file. 1068// Expect: The status is kDex2OatNeeded. 1069TEST_F(OatFileAssistantTest, LongDexExtension) { 1070 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx"; 1071 Copy(GetDexSrc1(), dex_location); 1072 1073 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, false); 1074 1075 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, 1076 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 1077 1078 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 1079 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 1080 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 1081 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 1082 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 1083 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 1084 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 1085} 1086 1087// A task to generate a dex location. Used by the RaceToGenerate test. 1088class RaceGenerateTask : public Task { 1089 public: 1090 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location) 1091 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr) 1092 {} 1093 1094 void Run(Thread* self ATTRIBUTE_UNUSED) { 1095 // Load the dex files, and save a pointer to the loaded oat file, so that 1096 // we can verify only one oat file was loaded for the dex location. 1097 std::vector<std::unique_ptr<const DexFile>> dex_files; 1098 std::vector<std::string> error_msgs; 1099 const OatFile* oat_file = nullptr; 1100 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat( 1101 dex_location_.c_str(), 1102 oat_location_.c_str(), 1103 /*class_loader*/nullptr, 1104 /*dex_elements*/nullptr, 1105 &oat_file, 1106 &error_msgs); 1107 CHECK(!dex_files.empty()) << Join(error_msgs, '\n'); 1108 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation(); 1109 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile(); 1110 CHECK_EQ(loaded_oat_file_, oat_file); 1111 } 1112 1113 const OatFile* GetLoadedOatFile() const { 1114 return loaded_oat_file_; 1115 } 1116 1117 private: 1118 std::string dex_location_; 1119 std::string oat_location_; 1120 const OatFile* loaded_oat_file_; 1121}; 1122 1123// Test the case where multiple processes race to generate an oat file. 1124// This simulates multiple processes using multiple threads. 1125// 1126// We want unique Oat files to be loaded even when there is a race to load. 1127// TODO: The test case no longer tests locking the way it was intended since we now get multiple 1128// copies of the same Oat files mapped at different locations. 1129TEST_F(OatFileAssistantTest, RaceToGenerate) { 1130 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar"; 1131 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat"; 1132 1133 // We use the lib core dex file, because it's large, and hopefully should 1134 // take a while to generate. 1135 Copy(GetLibCoreDexFileNames()[0], dex_location); 1136 1137 const int kNumThreads = 32; 1138 Thread* self = Thread::Current(); 1139 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads); 1140 std::vector<std::unique_ptr<RaceGenerateTask>> tasks; 1141 for (int i = 0; i < kNumThreads; i++) { 1142 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location)); 1143 thread_pool.AddTask(self, task.get()); 1144 tasks.push_back(std::move(task)); 1145 } 1146 thread_pool.StartWorkers(self); 1147 thread_pool.Wait(self, true, false); 1148 1149 // Verify every task got a unique oat file. 1150 std::set<const OatFile*> oat_files; 1151 for (auto& task : tasks) { 1152 const OatFile* oat_file = task->GetLoadedOatFile(); 1153 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end()); 1154 oat_files.insert(oat_file); 1155 } 1156} 1157 1158// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is 1159// disabled. 1160// Expect: We should load the odex file non-executable. 1161TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) { 1162 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar"; 1163 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex"; 1164 1165 // Create the dex and odex files 1166 Copy(GetDexSrc1(), dex_location); 1167 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 1168 1169 // Load the oat using an executable oat file assistant. 1170 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 1171 1172 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1173 ASSERT_TRUE(oat_file.get() != nullptr); 1174 EXPECT_FALSE(oat_file->IsExecutable()); 1175 std::vector<std::unique_ptr<const DexFile>> dex_files; 1176 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 1177 EXPECT_EQ(1u, dex_files.size()); 1178} 1179 1180// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is 1181// disabled. 1182// Expect: We should load the odex file non-executable. 1183TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) { 1184 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar"; 1185 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex"; 1186 1187 // Create the dex and odex files 1188 Copy(GetMultiDexSrc1(), dex_location); 1189 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 1190 1191 // Load the oat using an executable oat file assistant. 1192 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false, true); 1193 1194 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1195 ASSERT_TRUE(oat_file.get() != nullptr); 1196 EXPECT_FALSE(oat_file->IsExecutable()); 1197 std::vector<std::unique_ptr<const DexFile>> dex_files; 1198 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 1199 EXPECT_EQ(2u, dex_files.size()); 1200} 1201 1202TEST(OatFileAssistantUtilsTest, DexFilenameToOdexFilename) { 1203 std::string error_msg; 1204 std::string odex_file; 1205 1206 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename( 1207 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg; 1208 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file); 1209 1210 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename( 1211 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg; 1212 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file); 1213 1214 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename( 1215 "nopath.jar", kArm, &odex_file, &error_msg)); 1216 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename( 1217 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg)); 1218} 1219 1220// Verify the dexopt status values from dalvik.system.DexFile 1221// match the OatFileAssistant::DexOptStatus values. 1222TEST_F(OatFileAssistantTest, DexOptStatusValues) { 1223 ScopedObjectAccess soa(Thread::Current()); 1224 StackHandleScope<1> hs(soa.Self()); 1225 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 1226 Handle<mirror::Class> dexfile( 1227 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;"))); 1228 ASSERT_FALSE(dexfile.Get() == nullptr); 1229 linker->EnsureInitialized(soa.Self(), dexfile, true, true); 1230 1231 ArtField* no_dexopt_needed = mirror::Class::FindStaticField( 1232 soa.Self(), dexfile, "NO_DEXOPT_NEEDED", "I"); 1233 ASSERT_FALSE(no_dexopt_needed == nullptr); 1234 EXPECT_EQ(no_dexopt_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1235 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, no_dexopt_needed->GetInt(dexfile.Get())); 1236 1237 ArtField* dex2oat_needed = mirror::Class::FindStaticField( 1238 soa.Self(), dexfile, "DEX2OAT_NEEDED", "I"); 1239 ASSERT_FALSE(dex2oat_needed == nullptr); 1240 EXPECT_EQ(dex2oat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1241 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, dex2oat_needed->GetInt(dexfile.Get())); 1242 1243 ArtField* patchoat_needed = mirror::Class::FindStaticField( 1244 soa.Self(), dexfile, "PATCHOAT_NEEDED", "I"); 1245 ASSERT_FALSE(patchoat_needed == nullptr); 1246 EXPECT_EQ(patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1247 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, patchoat_needed->GetInt(dexfile.Get())); 1248 1249 ArtField* self_patchoat_needed = mirror::Class::FindStaticField( 1250 soa.Self(), dexfile, "SELF_PATCHOAT_NEEDED", "I"); 1251 ASSERT_FALSE(self_patchoat_needed == nullptr); 1252 EXPECT_EQ(self_patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1253 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, self_patchoat_needed->GetInt(dexfile.Get())); 1254} 1255 1256// TODO: More Tests: 1257// * Image checksum change is out of date for kIntepretOnly, but not 1258// kVerifyAtRuntime. But target of kVerifyAtRuntime still says current 1259// kInterpretOnly is out of date. 1260// * Test class linker falls back to unquickened dex for DexNoOat 1261// * Test class linker falls back to unquickened dex for MultiDexNoOat 1262// * Test using secondary isa 1263// * Test for status of oat while oat is being generated (how?) 1264// * Test case where 32 and 64 bit boot class paths differ, 1265// and we ask IsInBootClassPath for a class in exactly one of the 32 or 1266// 64 bit boot class paths. 1267// * Test unexpected scenarios (?): 1268// - Dex is stripped, don't have odex. 1269// - Oat file corrupted after status check, before reload unexecutable 1270// because it's unrelocated and no dex2oat 1271// * Test unrelocated specific target compilation type can be relocated to 1272// make it up to date. 1273 1274} // namespace art 1275