oat_file_assistant_test.cc revision 5f946da9c362216e9144b142ec0e5b90073b836d
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 "oat_file_assistant.h" 18 19#include <algorithm> 20#include <fstream> 21#include <string> 22#include <vector> 23#include <sys/param.h> 24 25#include <backtrace/BacktraceMap.h> 26#include <gtest/gtest.h> 27 28#include "art_field-inl.h" 29#include "class_linker-inl.h" 30#include "common_runtime_test.h" 31#include "compiler_callbacks.h" 32#include "gc/space/image_space.h" 33#include "mem_map.h" 34#include "os.h" 35#include "scoped_thread_state_change.h" 36#include "thread-inl.h" 37#include "utils.h" 38 39namespace art { 40 41class OatFileAssistantTest : public CommonRuntimeTest { 42 public: 43 virtual void SetUp() { 44 ReserveImageSpace(); 45 CommonRuntimeTest::SetUp(); 46 47 // Create a scratch directory to work from. 48 scratch_dir_ = android_data_ + "/OatFileAssistantTest"; 49 ASSERT_EQ(0, mkdir(scratch_dir_.c_str(), 0700)); 50 51 // Create a subdirectory in scratch for odex files. 52 odex_oat_dir_ = scratch_dir_ + "/oat"; 53 ASSERT_EQ(0, mkdir(odex_oat_dir_.c_str(), 0700)); 54 55 odex_dir_ = odex_oat_dir_ + "/" + std::string(GetInstructionSetString(kRuntimeISA)); 56 ASSERT_EQ(0, mkdir(odex_dir_.c_str(), 0700)); 57 58 59 // Verify the environment is as we expect 60 uint32_t checksum; 61 std::string error_msg; 62 ASSERT_TRUE(OS::FileExists(GetImageFile().c_str())) 63 << "Expected pre-compiled boot image to be at: " << GetImageFile(); 64 ASSERT_TRUE(OS::FileExists(GetDexSrc1().c_str())) 65 << "Expected dex file to be at: " << GetDexSrc1(); 66 ASSERT_TRUE(OS::FileExists(GetStrippedDexSrc1().c_str())) 67 << "Expected stripped dex file to be at: " << GetStrippedDexSrc1(); 68 ASSERT_FALSE(DexFile::GetChecksum(GetStrippedDexSrc1().c_str(), &checksum, &error_msg)) 69 << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1(); 70 ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str())) 71 << "Expected dex file to be at: " << GetDexSrc2(); 72 73 // GetMultiDexSrc2 should have the same primary dex checksum as 74 // GetMultiDexSrc1, but a different secondary dex checksum. 75 std::vector<std::unique_ptr<const DexFile>> multi1; 76 ASSERT_TRUE(DexFile::Open(GetMultiDexSrc1().c_str(), 77 GetMultiDexSrc1().c_str(), &error_msg, &multi1)) << error_msg; 78 ASSERT_GT(multi1.size(), 1u); 79 80 std::vector<std::unique_ptr<const DexFile>> multi2; 81 ASSERT_TRUE(DexFile::Open(GetMultiDexSrc2().c_str(), 82 GetMultiDexSrc2().c_str(), &error_msg, &multi2)) << error_msg; 83 ASSERT_GT(multi2.size(), 1u); 84 85 ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum()); 86 ASSERT_NE(multi1[1]->GetLocationChecksum(), multi2[1]->GetLocationChecksum()); 87 } 88 89 virtual void SetUpRuntimeOptions(RuntimeOptions* options) { 90 // options->push_back(std::make_pair("-verbose:oat", nullptr)); 91 92 // Set up the image location. 93 options->push_back(std::make_pair("-Ximage:" + GetImageLocation(), 94 nullptr)); 95 // Make sure compilercallbacks are not set so that relocation will be 96 // enabled. 97 callbacks_.reset(); 98 } 99 100 virtual void PreRuntimeCreate() { 101 UnreserveImageSpace(); 102 } 103 104 virtual void PostRuntimeCreate() { 105 ReserveImageSpace(); 106 } 107 108 virtual void TearDown() { 109 ClearDirectory(odex_dir_.c_str()); 110 ASSERT_EQ(0, rmdir(odex_dir_.c_str())); 111 112 ClearDirectory(odex_oat_dir_.c_str()); 113 ASSERT_EQ(0, rmdir(odex_oat_dir_.c_str())); 114 115 ClearDirectory(scratch_dir_.c_str()); 116 ASSERT_EQ(0, rmdir(scratch_dir_.c_str())); 117 118 CommonRuntimeTest::TearDown(); 119 } 120 121 void Copy(std::string src, std::string dst) { 122 std::ifstream src_stream(src, std::ios::binary); 123 std::ofstream dst_stream(dst, std::ios::binary); 124 125 dst_stream << src_stream.rdbuf(); 126 } 127 128 // Returns the directory where the pre-compiled core.art can be found. 129 // TODO: We should factor out this into common tests somewhere rather than 130 // re-hardcoding it here (This was copied originally from the elf writer 131 // test). 132 std::string GetImageDirectory() { 133 if (IsHost()) { 134 const char* host_dir = getenv("ANDROID_HOST_OUT"); 135 CHECK(host_dir != nullptr); 136 return std::string(host_dir) + "/framework"; 137 } else { 138 return std::string("/data/art-test"); 139 } 140 } 141 142 std::string GetImageLocation() { 143 return GetImageDirectory() + "/core.art"; 144 } 145 146 std::string GetImageFile() { 147 return GetImageDirectory() + "/" + GetInstructionSetString(kRuntimeISA) 148 + "/core.art"; 149 } 150 151 std::string GetDexSrc1() { 152 return GetTestDexFileName("Main"); 153 } 154 155 // Returns the path to a dex file equivalent to GetDexSrc1, but with the dex 156 // file stripped. 157 std::string GetStrippedDexSrc1() { 158 return GetTestDexFileName("MainStripped"); 159 } 160 161 std::string GetMultiDexSrc1() { 162 return GetTestDexFileName("MultiDex"); 163 } 164 165 // Returns the path to a multidex file equivalent to GetMultiDexSrc2, but 166 // with the contents of the secondary dex file changed. 167 std::string GetMultiDexSrc2() { 168 return GetTestDexFileName("MultiDexModifiedSecondary"); 169 } 170 171 std::string GetDexSrc2() { 172 return GetTestDexFileName("Nested"); 173 } 174 175 // Scratch directory, for dex and odex files (oat files will go in the 176 // dalvik cache). 177 std::string GetScratchDir() { 178 return scratch_dir_; 179 } 180 181 // Odex directory is the subdirectory in the scratch directory where odex 182 // files should be located. 183 std::string GetOdexDir() { 184 return odex_dir_; 185 } 186 187 // Generate an odex file for the purposes of test. 188 // If pic is true, generates a PIC odex. 189 void GenerateOdexForTest(const std::string& dex_location, 190 const std::string& odex_location, 191 bool pic = false) { 192 // For this operation, we temporarily redirect the dalvik cache so dex2oat 193 // doesn't find the relocated image file. 194 std::string android_data_tmp = GetScratchDir() + "AndroidDataTmp"; 195 setenv("ANDROID_DATA", android_data_tmp.c_str(), 1); 196 std::vector<std::string> args; 197 args.push_back("--dex-file=" + dex_location); 198 args.push_back("--oat-file=" + odex_location); 199 if (pic) { 200 args.push_back("--compile-pic"); 201 } else { 202 args.push_back("--include-patch-information"); 203 204 // We need to use the quick compiler to generate non-PIC code, because 205 // the optimizing compiler always generates PIC. 206 args.push_back("--compiler-backend=Quick"); 207 } 208 args.push_back("--runtime-arg"); 209 args.push_back("-Xnorelocate"); 210 std::string error_msg; 211 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg; 212 setenv("ANDROID_DATA", android_data_.c_str(), 1); 213 } 214 215 void GeneratePicOdexForTest(const std::string& dex_location, 216 const std::string& odex_location) { 217 GenerateOdexForTest(dex_location, odex_location, true); 218 } 219 220 private: 221 // Reserve memory around where the image will be loaded so other memory 222 // won't conflict when it comes time to load the image. 223 // This can be called with an already loaded image to reserve the space 224 // around it. 225 void ReserveImageSpace() { 226 MemMap::Init(); 227 228 // Ensure a chunk of memory is reserved for the image space. 229 uintptr_t reservation_start = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MIN_DELTA; 230 uintptr_t reservation_end = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MAX_DELTA 231 // Include the main space that has to come right after the 232 // image in case of the GSS collector. 233 + 384 * MB; 234 235 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) { 239 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 } 244 245 // 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; 250 image_reservation_.push_back(std::unique_ptr<MemMap>( 251 MemMap::MapAnonymous("image reservation", 252 reinterpret_cast<uint8_t*>(start), end - start, 253 PROT_NONE, false, false, &error_msg))); 254 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()); 258 } 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 268 std::string scratch_dir_; 269 std::string odex_oat_dir_; 270 std::string odex_dir_; 271 std::vector<std::unique_ptr<MemMap>> image_reservation_; 272}; 273 274class OatFileAssistantNoDex2OatTest : public OatFileAssistantTest { 275 public: 276 virtual void SetUpRuntimeOptions(RuntimeOptions* options) { 277 OatFileAssistantTest::SetUpRuntimeOptions(options); 278 options->push_back(std::make_pair("-Xnodex2oat", nullptr)); 279 } 280}; 281 282// Generate an oat file for the purposes of test, as opposed to testing 283// generation of oat files. 284static void GenerateOatForTest(const char* dex_location) { 285 OatFileAssistant oat_file_assistant(dex_location, kRuntimeISA, false); 286 287 std::string error_msg; 288 ASSERT_TRUE(oat_file_assistant.GenerateOatFile(&error_msg)) << error_msg; 289} 290 291// Case: We have a DEX file, but no OAT file for it. 292// Expect: The status is kDex2OatNeeded. 293TEST_F(OatFileAssistantTest, DexNoOat) { 294 std::string dex_location = GetScratchDir() + "/DexNoOat.jar"; 295 Copy(GetDexSrc1(), dex_location); 296 297 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 298 299 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); 300 301 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 302 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 303 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 304 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 305 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 306 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OdexFileStatus()); 307 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 308 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 309 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 310 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 311 EXPECT_EQ(OatFileAssistant::kOatOutOfDate, oat_file_assistant.OatFileStatus()); 312 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 313} 314 315// Case: We have no DEX file and no OAT file. 316// Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash. 317TEST_F(OatFileAssistantTest, NoDexNoOat) { 318 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar"; 319 320 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 321 322 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 323 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 324 325 // Trying to make the oat file up to date should not fail or crash. 326 std::string error_msg; 327 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)); 328 329 // Trying to get the best oat file should fail, but not crash. 330 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 331 EXPECT_EQ(nullptr, oat_file.get()); 332} 333 334// Case: We have a DEX file and up-to-date OAT file for it. 335// Expect: The status is kNoDexOptNeeded. 336TEST_F(OatFileAssistantTest, OatUpToDate) { 337 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar"; 338 Copy(GetDexSrc1(), dex_location); 339 GenerateOatForTest(dex_location.c_str()); 340 341 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 342 343 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 344 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 345 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 346 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 347 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 348 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 349 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 350 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 351 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 352 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus()); 353 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 354} 355 356// Case: We have a MultiDEX file and up-to-date OAT file for it. 357// Expect: The status is kNoDexOptNeeded and we load all dex files. 358TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) { 359 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar"; 360 Copy(GetMultiDexSrc1(), dex_location); 361 GenerateOatForTest(dex_location.c_str()); 362 363 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 364 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 365 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 366 367 // Verify we can load both dex files. 368 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 369 ASSERT_TRUE(oat_file.get() != nullptr); 370 EXPECT_TRUE(oat_file->IsExecutable()); 371 std::vector<std::unique_ptr<const DexFile>> dex_files; 372 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 373 EXPECT_EQ(2u, dex_files.size()); 374} 375 376// Case: We have a MultiDEX file where the secondary dex file is out of date. 377// Expect: The status is kDex2OatNeeded. 378TEST_F(OatFileAssistantTest, MultiDexSecondaryOutOfDate) { 379 std::string dex_location = GetScratchDir() + "/MultiDexSecondaryOutOfDate.jar"; 380 381 // Compile code for GetMultiDexSrc1. 382 Copy(GetMultiDexSrc1(), dex_location); 383 GenerateOatForTest(dex_location.c_str()); 384 385 // Now overwrite the dex file with GetMultiDexSrc2 so the secondary checksum 386 // is out of date. 387 Copy(GetMultiDexSrc2(), dex_location); 388 389 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 390 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); 391 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 392} 393 394// Case: We have a MultiDEX file and up-to-date OAT file for it with relative 395// encoded dex locations. 396// Expect: The oat file status is kNoDexOptNeeded. 397TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) { 398 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar"; 399 std::string oat_location = GetOdexDir() + "/RelativeEncodedDexLocation.oat"; 400 401 // Create the dex file 402 Copy(GetMultiDexSrc1(), dex_location); 403 404 // Create the oat file with relative encoded dex location. 405 std::vector<std::string> args; 406 args.push_back("--dex-file=" + dex_location); 407 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar")); 408 args.push_back("--oat-file=" + oat_location); 409 410 std::string error_msg; 411 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg; 412 413 // Verify we can load both dex files. 414 OatFileAssistant oat_file_assistant(dex_location.c_str(), 415 oat_location.c_str(), 416 kRuntimeISA, true); 417 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 418 ASSERT_TRUE(oat_file.get() != nullptr); 419 EXPECT_TRUE(oat_file->IsExecutable()); 420 std::vector<std::unique_ptr<const DexFile>> dex_files; 421 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 422 EXPECT_EQ(2u, dex_files.size()); 423} 424 425// Case: We have a DEX file and out-of-date OAT file. 426// Expect: The status is kDex2OatNeeded. 427TEST_F(OatFileAssistantTest, OatOutOfDate) { 428 std::string dex_location = GetScratchDir() + "/OatOutOfDate.jar"; 429 430 // We create a dex, generate an oat for it, then overwrite the dex with a 431 // different dex to make the oat out of date. 432 Copy(GetDexSrc1(), dex_location); 433 GenerateOatForTest(dex_location.c_str()); 434 Copy(GetDexSrc2(), dex_location); 435 436 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 437 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); 438 439 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 440 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 441 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 442 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 443 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 444 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 445 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 446 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 447} 448 449// Case: We have a DEX file and an ODEX file, but no OAT file. 450// Expect: The status is kPatchOatNeeded. 451TEST_F(OatFileAssistantTest, DexOdexNoOat) { 452 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar"; 453 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex"; 454 455 // Create the dex and odex files 456 Copy(GetDexSrc1(), dex_location); 457 GenerateOdexForTest(dex_location, odex_location); 458 459 // Verify the status. 460 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 461 462 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 463 464 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 465 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 466 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 467 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 468 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation()); 469 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 470 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 471 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 472 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 473 474 // We should still be able to get the non-executable odex file to run from. 475 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 476 ASSERT_TRUE(oat_file.get() != nullptr); 477} 478 479// Case: We have a stripped DEX file and an ODEX file, but no OAT file. 480// Expect: The status is kPatchOatNeeded 481TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) { 482 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar"; 483 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex"; 484 485 // Create the dex and odex files 486 Copy(GetDexSrc1(), dex_location); 487 GenerateOdexForTest(dex_location, odex_location); 488 489 // Strip the dex file 490 Copy(GetStrippedDexSrc1(), dex_location); 491 492 // Verify the status. 493 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 494 495 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 496 497 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 498 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 499 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 500 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 501 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 502 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 503 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 504 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 505 506 // Make the oat file up to date. 507 std::string error_msg; 508 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 509 510 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 511 512 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 513 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 514 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 515 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 516 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 517 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 518 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 519 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 520 521 // Verify we can load the dex files from it. 522 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 523 ASSERT_TRUE(oat_file.get() != nullptr); 524 EXPECT_TRUE(oat_file->IsExecutable()); 525 std::vector<std::unique_ptr<const DexFile>> dex_files; 526 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 527 EXPECT_EQ(1u, dex_files.size()); 528} 529 530// Case: We have a stripped DEX file, an ODEX file, and an out-of-date OAT file. 531// Expect: The status is kPatchOatNeeded. 532TEST_F(OatFileAssistantTest, StrippedDexOdexOat) { 533 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar"; 534 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex"; 535 536 // Create the oat file from a different dex file so it looks out of date. 537 Copy(GetDexSrc2(), dex_location); 538 GenerateOatForTest(dex_location.c_str()); 539 540 // Create the odex file 541 Copy(GetDexSrc1(), dex_location); 542 GenerateOdexForTest(dex_location, odex_location); 543 544 // Strip the dex file. 545 Copy(GetStrippedDexSrc1(), dex_location); 546 547 // Verify the status. 548 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 549 550 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 551 552 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 553 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 554 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 555 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation()); 556 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 557 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 558 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 559 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 560 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 561 562 // Make the oat file up to date. 563 std::string error_msg; 564 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 565 566 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 567 568 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 569 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 570 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 571 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation()); 572 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 573 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 574 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 575 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 576 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 577 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 578 579 // Verify we can load the dex files from it. 580 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 581 ASSERT_TRUE(oat_file.get() != nullptr); 582 EXPECT_TRUE(oat_file->IsExecutable()); 583 std::vector<std::unique_ptr<const DexFile>> dex_files; 584 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 585 EXPECT_EQ(1u, dex_files.size()); 586} 587 588// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no 589// OAT file. Expect: The status is kNoDexOptNeeded. 590TEST_F(OatFileAssistantTest, ResourceOnlyDex) { 591 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar"; 592 593 Copy(GetStrippedDexSrc1(), dex_location); 594 595 // Verify the status. 596 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 597 598 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 599 600 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 601 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 602 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 603 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 604 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 605 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 606 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 607 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 608 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 609 610 // Make the oat file up to date. This should have no effect. 611 std::string error_msg; 612 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 613 614 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 615 616 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 617 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 618 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 619 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 620 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 621 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 622 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 623 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 624 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 625} 626 627// Case: We have a DEX file, no ODEX file and an OAT file that needs 628// relocation. 629// Expect: The status is kSelfPatchOatNeeded. 630TEST_F(OatFileAssistantTest, SelfRelocation) { 631 std::string dex_location = GetScratchDir() + "/SelfRelocation.jar"; 632 std::string oat_location = GetOdexDir() + "/SelfRelocation.oat"; 633 634 // Create the dex and odex files 635 Copy(GetDexSrc1(), dex_location); 636 GenerateOdexForTest(dex_location, oat_location); 637 638 OatFileAssistant oat_file_assistant(dex_location.c_str(), 639 oat_location.c_str(), kRuntimeISA, true); 640 641 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 642 643 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 644 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 645 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 646 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 647 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 648 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 649 EXPECT_TRUE(oat_file_assistant.OatFileNeedsRelocation()); 650 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 651 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 652 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 653 654 // Make the oat file up to date. 655 std::string error_msg; 656 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 657 658 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 659 660 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 661 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 662 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 663 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 664 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 665 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 666 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 667 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 668 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 669 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 670 671 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 672 ASSERT_TRUE(oat_file.get() != nullptr); 673 EXPECT_TRUE(oat_file->IsExecutable()); 674 std::vector<std::unique_ptr<const DexFile>> dex_files; 675 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 676 EXPECT_EQ(1u, dex_files.size()); 677} 678 679// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and 680// OAT files both have patch delta of 0. 681// Expect: It shouldn't crash, and status is kPatchOatNeeded. 682TEST_F(OatFileAssistantTest, OdexOatOverlap) { 683 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar"; 684 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex"; 685 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat"; 686 687 // Create the dex and odex files 688 Copy(GetDexSrc1(), dex_location); 689 GenerateOdexForTest(dex_location, odex_location); 690 691 // Create the oat file by copying the odex so they are located in the same 692 // place in memory. 693 Copy(odex_location, oat_location); 694 695 // Verify things don't go bad. 696 OatFileAssistant oat_file_assistant(dex_location.c_str(), 697 oat_location.c_str(), kRuntimeISA, true); 698 699 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 700 701 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 702 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 703 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 704 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 705 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 706 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 707 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 708 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 709 710 // Things aren't relocated, so it should fall back to interpreted. 711 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 712 ASSERT_TRUE(oat_file.get() != nullptr); 713 714 EXPECT_FALSE(oat_file->IsExecutable()); 715 std::vector<std::unique_ptr<const DexFile>> dex_files; 716 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 717 EXPECT_EQ(1u, dex_files.size()); 718 719 // Add some extra checks to help diagnose apparently flaky test failures. 720 Runtime* runtime = Runtime::Current(); 721 const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace(); 722 ASSERT_TRUE(image_space != nullptr); 723 const ImageHeader& image_header = image_space->GetImageHeader(); 724 const OatHeader& oat_header = oat_file->GetOatHeader(); 725 EXPECT_FALSE(oat_file->IsPic()); 726 EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum()); 727 EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()), 728 oat_header.GetImageFileLocationOatDataBegin()); 729 EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta()); 730} 731 732// Case: We have a DEX file and a PIC ODEX file, but no OAT file. 733// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation. 734TEST_F(OatFileAssistantTest, DexPicOdexNoOat) { 735 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar"; 736 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex"; 737 738 // Create the dex and odex files 739 Copy(GetDexSrc1(), dex_location); 740 GeneratePicOdexForTest(dex_location, odex_location); 741 742 // Verify the status. 743 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 744 745 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 746 747 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 748 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 749 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 750 EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate()); 751 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 752 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 753 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 754 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 755} 756 757// Case: We have a DEX file and up-to-date OAT file for it. 758// Expect: We should load an executable dex file. 759TEST_F(OatFileAssistantTest, LoadOatUpToDate) { 760 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar"; 761 762 Copy(GetDexSrc1(), dex_location); 763 GenerateOatForTest(dex_location.c_str()); 764 765 // Load the oat using an oat file assistant. 766 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 767 768 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 769 ASSERT_TRUE(oat_file.get() != nullptr); 770 EXPECT_TRUE(oat_file->IsExecutable()); 771 std::vector<std::unique_ptr<const DexFile>> dex_files; 772 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 773 EXPECT_EQ(1u, dex_files.size()); 774} 775 776// Case: We have a DEX file and up-to-date OAT file for it. 777// Expect: Loading non-executable should load the oat non-executable. 778TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) { 779 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar"; 780 781 Copy(GetDexSrc1(), dex_location); 782 GenerateOatForTest(dex_location.c_str()); 783 784 // Load the oat using an oat file assistant. 785 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 786 787 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 788 ASSERT_TRUE(oat_file.get() != nullptr); 789 EXPECT_FALSE(oat_file->IsExecutable()); 790 std::vector<std::unique_ptr<const DexFile>> dex_files; 791 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 792 EXPECT_EQ(1u, dex_files.size()); 793} 794 795// Case: We have a DEX file. 796// Expect: We should load an executable dex file from an alternative oat 797// location. 798TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) { 799 std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar"; 800 std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat"; 801 802 Copy(GetDexSrc1(), dex_location); 803 804 OatFileAssistant oat_file_assistant( 805 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true); 806 std::string error_msg; 807 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 808 809 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 810 ASSERT_TRUE(oat_file.get() != nullptr); 811 EXPECT_TRUE(oat_file->IsExecutable()); 812 std::vector<std::unique_ptr<const DexFile>> dex_files; 813 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 814 EXPECT_EQ(1u, dex_files.size()); 815 816 EXPECT_TRUE(OS::FileExists(oat_location.c_str())); 817 818 // Verify it didn't create an oat in the default location. 819 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false); 820 EXPECT_FALSE(ofm.OatFileExists()); 821} 822 823// Turn an absolute path into a path relative to the current working 824// directory. 825static std::string MakePathRelative(std::string target) { 826 char buf[MAXPATHLEN]; 827 std::string cwd = getcwd(buf, MAXPATHLEN); 828 829 // Split the target and cwd paths into components. 830 std::vector<std::string> target_path; 831 std::vector<std::string> cwd_path; 832 Split(target, '/', &target_path); 833 Split(cwd, '/', &cwd_path); 834 835 // Reverse the path components, so we can use pop_back(). 836 std::reverse(target_path.begin(), target_path.end()); 837 std::reverse(cwd_path.begin(), cwd_path.end()); 838 839 // Drop the common prefix of the paths. Because we reversed the path 840 // components, this becomes the common suffix of target_path and cwd_path. 841 while (!target_path.empty() && !cwd_path.empty() 842 && target_path.back() == cwd_path.back()) { 843 target_path.pop_back(); 844 cwd_path.pop_back(); 845 } 846 847 // For each element of the remaining cwd_path, add '..' to the beginning 848 // of the target path. Because we reversed the path components, we add to 849 // the end of target_path. 850 for (unsigned int i = 0; i < cwd_path.size(); i++) { 851 target_path.push_back(".."); 852 } 853 854 // Reverse again to get the right path order, and join to get the result. 855 std::reverse(target_path.begin(), target_path.end()); 856 return Join(target_path, '/'); 857} 858 859// Case: Non-absolute path to Dex location. 860// Expect: Not sure, but it shouldn't crash. 861TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) { 862 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar"; 863 Copy(GetDexSrc1(), abs_dex_location); 864 865 std::string dex_location = MakePathRelative(abs_dex_location); 866 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 867 868 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 869 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); 870 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 871 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 872 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 873 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 874 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 875 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 876} 877 878// Case: Very short, non-existent Dex location. 879// Expect: kNoDexOptNeeded. 880TEST_F(OatFileAssistantTest, ShortDexLocation) { 881 std::string dex_location = "/xx"; 882 883 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 884 885 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 886 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 887 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 888 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 889 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 890 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 891 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 892 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 893 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 894 895 // Trying to make it up to date should have no effect. 896 std::string error_msg; 897 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)); 898 EXPECT_TRUE(error_msg.empty()); 899} 900 901// Case: Non-standard extension for dex file. 902// Expect: The status is kDex2OatNeeded. 903TEST_F(OatFileAssistantTest, LongDexExtension) { 904 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx"; 905 Copy(GetDexSrc1(), dex_location); 906 907 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 908 909 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); 910 911 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 912 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 913 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 914 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 915 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 916 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 917 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 918} 919 920// A task to generate a dex location. Used by the RaceToGenerate test. 921class RaceGenerateTask : public Task { 922 public: 923 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location) 924 : dex_location_(dex_location), oat_location_(oat_location), 925 loaded_oat_file_(nullptr) 926 {} 927 928 void Run(Thread* self) { 929 UNUSED(self); 930 931 // Load the dex files, and save a pointer to the loaded oat file, so that 932 // we can verify only one oat file was loaded for the dex location. 933 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 934 std::vector<std::unique_ptr<const DexFile>> dex_files; 935 std::vector<std::string> error_msgs; 936 dex_files = linker->OpenDexFilesFromOat(dex_location_.c_str(), oat_location_.c_str(), &error_msgs); 937 CHECK(!dex_files.empty()) << Join(error_msgs, '\n'); 938 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation(); 939 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile(); 940 } 941 942 const OatFile* GetLoadedOatFile() const { 943 return loaded_oat_file_; 944 } 945 946 private: 947 std::string dex_location_; 948 std::string oat_location_; 949 const OatFile* loaded_oat_file_; 950}; 951 952// Test the case where multiple processes race to generate an oat file. 953// This simulates multiple processes using multiple threads. 954// 955// We want only one Oat file to be loaded when there is a race to load, to 956// avoid using up the virtual memory address space. 957TEST_F(OatFileAssistantTest, RaceToGenerate) { 958 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar"; 959 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat"; 960 961 // We use the lib core dex file, because it's large, and hopefully should 962 // take a while to generate. 963 Copy(GetLibCoreDexFileName(), dex_location); 964 965 const int kNumThreads = 32; 966 Thread* self = Thread::Current(); 967 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads); 968 std::vector<std::unique_ptr<RaceGenerateTask>> tasks; 969 for (int i = 0; i < kNumThreads; i++) { 970 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location)); 971 thread_pool.AddTask(self, task.get()); 972 tasks.push_back(std::move(task)); 973 } 974 thread_pool.StartWorkers(self); 975 thread_pool.Wait(self, true, false); 976 977 // Verify every task got the same pointer. 978 const OatFile* expected = tasks[0]->GetLoadedOatFile(); 979 for (auto& task : tasks) { 980 EXPECT_EQ(expected, task->GetLoadedOatFile()); 981 } 982} 983 984// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is 985// disabled. 986// Expect: We should load the odex file non-executable. 987TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) { 988 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar"; 989 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex"; 990 991 // Create the dex and odex files 992 Copy(GetDexSrc1(), dex_location); 993 GenerateOdexForTest(dex_location, odex_location); 994 995 // Load the oat using an executable oat file assistant. 996 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 997 998 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 999 ASSERT_TRUE(oat_file.get() != nullptr); 1000 EXPECT_FALSE(oat_file->IsExecutable()); 1001 std::vector<std::unique_ptr<const DexFile>> dex_files; 1002 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 1003 EXPECT_EQ(1u, dex_files.size()); 1004} 1005 1006// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is 1007// disabled. 1008// Expect: We should load the odex file non-executable. 1009TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) { 1010 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar"; 1011 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex"; 1012 1013 // Create the dex and odex files 1014 Copy(GetMultiDexSrc1(), dex_location); 1015 GenerateOdexForTest(dex_location, odex_location); 1016 1017 // Load the oat using an executable oat file assistant. 1018 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 1019 1020 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1021 ASSERT_TRUE(oat_file.get() != nullptr); 1022 EXPECT_FALSE(oat_file->IsExecutable()); 1023 std::vector<std::unique_ptr<const DexFile>> dex_files; 1024 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 1025 EXPECT_EQ(2u, dex_files.size()); 1026} 1027 1028TEST(OatFileAssistantUtilsTest, DexFilenameToOdexFilename) { 1029 std::string error_msg; 1030 std::string odex_file; 1031 1032 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename( 1033 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg; 1034 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file); 1035 1036 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename( 1037 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg; 1038 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file); 1039 1040 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename( 1041 "nopath.jar", kArm, &odex_file, &error_msg)); 1042 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename( 1043 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg)); 1044} 1045 1046// Verify the dexopt status values from dalvik.system.DexFile 1047// match the OatFileAssistant::DexOptStatus values. 1048TEST_F(OatFileAssistantTest, DexOptStatusValues) { 1049 ScopedObjectAccess soa(Thread::Current()); 1050 StackHandleScope<1> hs(soa.Self()); 1051 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 1052 Handle<mirror::Class> dexfile( 1053 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;"))); 1054 ASSERT_FALSE(dexfile.Get() == nullptr); 1055 linker->EnsureInitialized(soa.Self(), dexfile, true, true); 1056 1057 ArtField* no_dexopt_needed = mirror::Class::FindStaticField( 1058 soa.Self(), dexfile, "NO_DEXOPT_NEEDED", "I"); 1059 ASSERT_FALSE(no_dexopt_needed == nullptr); 1060 EXPECT_EQ(no_dexopt_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1061 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, no_dexopt_needed->GetInt(dexfile.Get())); 1062 1063 ArtField* dex2oat_needed = mirror::Class::FindStaticField( 1064 soa.Self(), dexfile, "DEX2OAT_NEEDED", "I"); 1065 ASSERT_FALSE(dex2oat_needed == nullptr); 1066 EXPECT_EQ(dex2oat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1067 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, dex2oat_needed->GetInt(dexfile.Get())); 1068 1069 ArtField* patchoat_needed = mirror::Class::FindStaticField( 1070 soa.Self(), dexfile, "PATCHOAT_NEEDED", "I"); 1071 ASSERT_FALSE(patchoat_needed == nullptr); 1072 EXPECT_EQ(patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1073 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, patchoat_needed->GetInt(dexfile.Get())); 1074 1075 ArtField* self_patchoat_needed = mirror::Class::FindStaticField( 1076 soa.Self(), dexfile, "SELF_PATCHOAT_NEEDED", "I"); 1077 ASSERT_FALSE(self_patchoat_needed == nullptr); 1078 EXPECT_EQ(self_patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1079 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, self_patchoat_needed->GetInt(dexfile.Get())); 1080} 1081 1082// TODO: More Tests: 1083// * Test class linker falls back to unquickened dex for DexNoOat 1084// * Test class linker falls back to unquickened dex for MultiDexNoOat 1085// * Test using secondary isa 1086// * Test with profiling info? 1087// * Test for status of oat while oat is being generated (how?) 1088// * Test case where 32 and 64 bit boot class paths differ, 1089// and we ask IsInBootClassPath for a class in exactly one of the 32 or 1090// 64 bit boot class paths. 1091// * Test unexpected scenarios (?): 1092// - Dex is stripped, don't have odex. 1093// - Oat file corrupted after status check, before reload unexecutable 1094// because it's unrelocated and no dex2oat 1095 1096} // namespace art 1097