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 475// Case: We have a stripped DEX file and an ODEX file, but no OAT file. 476// Expect: The status is kPatchOatNeeded 477TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) { 478 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar"; 479 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex"; 480 481 // Create the dex and odex files 482 Copy(GetDexSrc1(), dex_location); 483 GenerateOdexForTest(dex_location, odex_location); 484 485 // Strip the dex file 486 Copy(GetStrippedDexSrc1(), dex_location); 487 488 // Verify the status. 489 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 490 491 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 492 493 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 494 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 495 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 496 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 497 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 498 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 499 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 500 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 501 502 // Make the oat file up to date. 503 std::string error_msg; 504 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 505 506 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 507 508 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 509 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 510 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 511 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 512 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 513 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 514 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 515 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 516 517 // Verify we can load the dex files from it. 518 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 519 ASSERT_TRUE(oat_file.get() != nullptr); 520 EXPECT_TRUE(oat_file->IsExecutable()); 521 std::vector<std::unique_ptr<const DexFile>> dex_files; 522 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 523 EXPECT_EQ(1u, dex_files.size()); 524} 525 526// Case: We have a stripped DEX file, an ODEX file, and an out-of-date OAT file. 527// Expect: The status is kPatchOatNeeded. 528TEST_F(OatFileAssistantTest, StrippedDexOdexOat) { 529 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar"; 530 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex"; 531 532 // Create the oat file from a different dex file so it looks out of date. 533 Copy(GetDexSrc2(), dex_location); 534 GenerateOatForTest(dex_location.c_str()); 535 536 // Create the odex file 537 Copy(GetDexSrc1(), dex_location); 538 GenerateOdexForTest(dex_location, odex_location); 539 540 // Strip the dex file. 541 Copy(GetStrippedDexSrc1(), dex_location); 542 543 // Verify the status. 544 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 545 546 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 547 548 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 549 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 550 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 551 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation()); 552 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 553 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 554 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 555 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 556 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 557 558 // Make the oat file up to date. 559 std::string error_msg; 560 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 561 562 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 563 564 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 565 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 566 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 567 EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation()); 568 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 569 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 570 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 571 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 572 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 573 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 574 575 // Verify we can load the dex files from it. 576 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 577 ASSERT_TRUE(oat_file.get() != nullptr); 578 EXPECT_TRUE(oat_file->IsExecutable()); 579 std::vector<std::unique_ptr<const DexFile>> dex_files; 580 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 581 EXPECT_EQ(1u, dex_files.size()); 582} 583 584// Case: We have a stripped (or resource-only) DEX file, no ODEX file and no 585// OAT file. Expect: The status is kNoDexOptNeeded. 586TEST_F(OatFileAssistantTest, ResourceOnlyDex) { 587 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar"; 588 589 Copy(GetStrippedDexSrc1(), dex_location); 590 591 // Verify the status. 592 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 593 594 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 595 596 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 597 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 598 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 599 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 600 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 601 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 602 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 603 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 604 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 605 606 // Make the oat file up to date. This should have no effect. 607 std::string error_msg; 608 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 609 610 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 611 612 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 613 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 614 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 615 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 616 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 617 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 618 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 619 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 620 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 621} 622 623// Case: We have a DEX file, no ODEX file and an OAT file that needs 624// relocation. 625// Expect: The status is kSelfPatchOatNeeded. 626TEST_F(OatFileAssistantTest, SelfRelocation) { 627 std::string dex_location = GetScratchDir() + "/SelfRelocation.jar"; 628 std::string oat_location = GetOdexDir() + "/SelfRelocation.oat"; 629 630 // Create the dex and odex files 631 Copy(GetDexSrc1(), dex_location); 632 GenerateOdexForTest(dex_location, oat_location); 633 634 OatFileAssistant oat_file_assistant(dex_location.c_str(), 635 oat_location.c_str(), kRuntimeISA, true); 636 637 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 638 639 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 640 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 641 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 642 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 643 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 644 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 645 EXPECT_TRUE(oat_file_assistant.OatFileNeedsRelocation()); 646 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 647 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 648 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 649 650 // Make the oat file up to date. 651 std::string error_msg; 652 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 653 654 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 655 656 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 657 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 658 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 659 EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation()); 660 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 661 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 662 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 663 EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation()); 664 EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate()); 665 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 666 667 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 668 ASSERT_TRUE(oat_file.get() != nullptr); 669 EXPECT_TRUE(oat_file->IsExecutable()); 670 std::vector<std::unique_ptr<const DexFile>> dex_files; 671 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 672 EXPECT_EQ(1u, dex_files.size()); 673} 674 675// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and 676// OAT files both have patch delta of 0. 677// Expect: It shouldn't crash, and status is kPatchOatNeeded. 678TEST_F(OatFileAssistantTest, OdexOatOverlap) { 679 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar"; 680 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex"; 681 std::string oat_location = GetOdexDir() + "/OdexOatOverlap.oat"; 682 683 // Create the dex and odex files 684 Copy(GetDexSrc1(), dex_location); 685 GenerateOdexForTest(dex_location, odex_location); 686 687 // Create the oat file by copying the odex so they are located in the same 688 // place in memory. 689 Copy(odex_location, oat_location); 690 691 // Verify things don't go bad. 692 OatFileAssistant oat_file_assistant(dex_location.c_str(), 693 oat_location.c_str(), kRuntimeISA, true); 694 695 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, oat_file_assistant.GetDexOptNeeded()); 696 697 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 698 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 699 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 700 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 701 EXPECT_TRUE(oat_file_assistant.OatFileExists()); 702 EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate()); 703 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 704 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 705 706 // Things aren't relocated, so it should fall back to interpreted. 707 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 708 ASSERT_TRUE(oat_file.get() != nullptr); 709 710 EXPECT_FALSE(oat_file->IsExecutable()); 711 std::vector<std::unique_ptr<const DexFile>> dex_files; 712 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 713 EXPECT_EQ(1u, dex_files.size()); 714 715 // Add some extra checks to help diagnose apparently flaky test failures. 716 Runtime* runtime = Runtime::Current(); 717 const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace(); 718 ASSERT_TRUE(image_space != nullptr); 719 const ImageHeader& image_header = image_space->GetImageHeader(); 720 const OatHeader& oat_header = oat_file->GetOatHeader(); 721 EXPECT_FALSE(oat_file->IsPic()); 722 EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum()); 723 EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()), 724 oat_header.GetImageFileLocationOatDataBegin()); 725 EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta()); 726} 727 728// Case: We have a DEX file and a PIC ODEX file, but no OAT file. 729// Expect: The status is kNoDexOptNeeded, because PIC needs no relocation. 730TEST_F(OatFileAssistantTest, DexPicOdexNoOat) { 731 std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar"; 732 std::string odex_location = GetOdexDir() + "/DexPicOdexNoOat.odex"; 733 734 // Create the dex and odex files 735 Copy(GetDexSrc1(), dex_location); 736 GeneratePicOdexForTest(dex_location, odex_location); 737 738 // Verify the status. 739 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 740 741 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 742 743 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 744 EXPECT_TRUE(oat_file_assistant.OdexFileExists()); 745 EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate()); 746 EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate()); 747 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 748 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 749 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 750 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 751} 752 753// Case: We have a DEX file and up-to-date OAT file for it. 754// Expect: We should load an executable dex file. 755TEST_F(OatFileAssistantTest, LoadOatUpToDate) { 756 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar"; 757 758 Copy(GetDexSrc1(), dex_location); 759 GenerateOatForTest(dex_location.c_str()); 760 761 // Load the oat using an oat file assistant. 762 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 763 764 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 765 ASSERT_TRUE(oat_file.get() != nullptr); 766 EXPECT_TRUE(oat_file->IsExecutable()); 767 std::vector<std::unique_ptr<const DexFile>> dex_files; 768 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 769 EXPECT_EQ(1u, dex_files.size()); 770} 771 772// Case: We have a DEX file and up-to-date OAT file for it. 773// Expect: Loading non-executable should load the oat non-executable. 774TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) { 775 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar"; 776 777 Copy(GetDexSrc1(), dex_location); 778 GenerateOatForTest(dex_location.c_str()); 779 780 // Load the oat using an oat file assistant. 781 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 782 783 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 784 ASSERT_TRUE(oat_file.get() != nullptr); 785 EXPECT_FALSE(oat_file->IsExecutable()); 786 std::vector<std::unique_ptr<const DexFile>> dex_files; 787 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 788 EXPECT_EQ(1u, dex_files.size()); 789} 790 791// Case: We have a DEX file. 792// Expect: We should load an executable dex file from an alternative oat 793// location. 794TEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) { 795 std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar"; 796 std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat"; 797 798 Copy(GetDexSrc1(), dex_location); 799 800 OatFileAssistant oat_file_assistant( 801 dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true); 802 std::string error_msg; 803 ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg; 804 805 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 806 ASSERT_TRUE(oat_file.get() != nullptr); 807 EXPECT_TRUE(oat_file->IsExecutable()); 808 std::vector<std::unique_ptr<const DexFile>> dex_files; 809 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 810 EXPECT_EQ(1u, dex_files.size()); 811 812 EXPECT_TRUE(OS::FileExists(oat_location.c_str())); 813 814 // Verify it didn't create an oat in the default location. 815 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false); 816 EXPECT_FALSE(ofm.OatFileExists()); 817} 818 819// Turn an absolute path into a path relative to the current working 820// directory. 821static std::string MakePathRelative(std::string target) { 822 char buf[MAXPATHLEN]; 823 std::string cwd = getcwd(buf, MAXPATHLEN); 824 825 // Split the target and cwd paths into components. 826 std::vector<std::string> target_path; 827 std::vector<std::string> cwd_path; 828 Split(target, '/', &target_path); 829 Split(cwd, '/', &cwd_path); 830 831 // Reverse the path components, so we can use pop_back(). 832 std::reverse(target_path.begin(), target_path.end()); 833 std::reverse(cwd_path.begin(), cwd_path.end()); 834 835 // Drop the common prefix of the paths. Because we reversed the path 836 // components, this becomes the common suffix of target_path and cwd_path. 837 while (!target_path.empty() && !cwd_path.empty() 838 && target_path.back() == cwd_path.back()) { 839 target_path.pop_back(); 840 cwd_path.pop_back(); 841 } 842 843 // For each element of the remaining cwd_path, add '..' to the beginning 844 // of the target path. Because we reversed the path components, we add to 845 // the end of target_path. 846 for (unsigned int i = 0; i < cwd_path.size(); i++) { 847 target_path.push_back(".."); 848 } 849 850 // Reverse again to get the right path order, and join to get the result. 851 std::reverse(target_path.begin(), target_path.end()); 852 return Join(target_path, '/'); 853} 854 855// Case: Non-absolute path to Dex location. 856// Expect: Not sure, but it shouldn't crash. 857TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) { 858 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar"; 859 Copy(GetDexSrc1(), abs_dex_location); 860 861 std::string dex_location = MakePathRelative(abs_dex_location); 862 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 863 864 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 865 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); 866 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 867 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 868 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 869 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 870 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 871 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 872} 873 874// Case: Very short, non-existent Dex location. 875// Expect: kNoDexOptNeeded. 876TEST_F(OatFileAssistantTest, ShortDexLocation) { 877 std::string dex_location = "/xx"; 878 879 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 880 881 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 882 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded()); 883 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 884 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 885 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 886 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 887 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 888 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 889 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 890 891 // Trying to make it up to date should have no effect. 892 std::string error_msg; 893 EXPECT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)); 894 EXPECT_TRUE(error_msg.empty()); 895} 896 897// Case: Non-standard extension for dex file. 898// Expect: The status is kDex2OatNeeded. 899TEST_F(OatFileAssistantTest, LongDexExtension) { 900 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx"; 901 Copy(GetDexSrc1(), dex_location); 902 903 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 904 905 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, oat_file_assistant.GetDexOptNeeded()); 906 907 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 908 EXPECT_FALSE(oat_file_assistant.OdexFileExists()); 909 EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate()); 910 EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate()); 911 EXPECT_FALSE(oat_file_assistant.OatFileExists()); 912 EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate()); 913 EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate()); 914} 915 916// A task to generate a dex location. Used by the RaceToGenerate test. 917class RaceGenerateTask : public Task { 918 public: 919 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location) 920 : dex_location_(dex_location), oat_location_(oat_location), 921 loaded_oat_file_(nullptr) 922 {} 923 924 void Run(Thread* self) { 925 UNUSED(self); 926 927 // Load the dex files, and save a pointer to the loaded oat file, so that 928 // we can verify only one oat file was loaded for the dex location. 929 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 930 std::vector<std::unique_ptr<const DexFile>> dex_files; 931 std::vector<std::string> error_msgs; 932 dex_files = linker->OpenDexFilesFromOat(dex_location_.c_str(), oat_location_.c_str(), &error_msgs); 933 CHECK(!dex_files.empty()) << Join(error_msgs, '\n'); 934 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation(); 935 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile(); 936 } 937 938 const OatFile* GetLoadedOatFile() const { 939 return loaded_oat_file_; 940 } 941 942 private: 943 std::string dex_location_; 944 std::string oat_location_; 945 const OatFile* loaded_oat_file_; 946}; 947 948// Test the case where multiple processes race to generate an oat file. 949// This simulates multiple processes using multiple threads. 950// 951// We want only one Oat file to be loaded when there is a race to load, to 952// avoid using up the virtual memory address space. 953TEST_F(OatFileAssistantTest, RaceToGenerate) { 954 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar"; 955 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat"; 956 957 // We use the lib core dex file, because it's large, and hopefully should 958 // take a while to generate. 959 Copy(GetLibCoreDexFileName(), dex_location); 960 961 const int kNumThreads = 32; 962 Thread* self = Thread::Current(); 963 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads); 964 std::vector<std::unique_ptr<RaceGenerateTask>> tasks; 965 for (int i = 0; i < kNumThreads; i++) { 966 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location)); 967 thread_pool.AddTask(self, task.get()); 968 tasks.push_back(std::move(task)); 969 } 970 thread_pool.StartWorkers(self); 971 thread_pool.Wait(self, true, false); 972 973 // Verify every task got the same pointer. 974 const OatFile* expected = tasks[0]->GetLoadedOatFile(); 975 for (auto& task : tasks) { 976 EXPECT_EQ(expected, task->GetLoadedOatFile()); 977 } 978} 979 980// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is 981// disabled. 982// Expect: We should load the odex file non-executable. 983TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) { 984 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar"; 985 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex"; 986 987 // Create the dex and odex files 988 Copy(GetDexSrc1(), dex_location); 989 GenerateOdexForTest(dex_location, odex_location); 990 991 // Load the oat using an executable oat file assistant. 992 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 993 994 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 995 ASSERT_TRUE(oat_file.get() != nullptr); 996 EXPECT_FALSE(oat_file->IsExecutable()); 997 std::vector<std::unique_ptr<const DexFile>> dex_files; 998 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 999 EXPECT_EQ(1u, dex_files.size()); 1000} 1001 1002// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is 1003// disabled. 1004// Expect: We should load the odex file non-executable. 1005TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) { 1006 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar"; 1007 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex"; 1008 1009 // Create the dex and odex files 1010 Copy(GetMultiDexSrc1(), dex_location); 1011 GenerateOdexForTest(dex_location, odex_location); 1012 1013 // Load the oat using an executable oat file assistant. 1014 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 1015 1016 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1017 ASSERT_TRUE(oat_file.get() != nullptr); 1018 EXPECT_FALSE(oat_file->IsExecutable()); 1019 std::vector<std::unique_ptr<const DexFile>> dex_files; 1020 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 1021 EXPECT_EQ(2u, dex_files.size()); 1022} 1023 1024TEST(OatFileAssistantUtilsTest, DexFilenameToOdexFilename) { 1025 std::string error_msg; 1026 std::string odex_file; 1027 1028 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename( 1029 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg; 1030 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file); 1031 1032 EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename( 1033 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg; 1034 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file); 1035 1036 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename( 1037 "nopath.jar", kArm, &odex_file, &error_msg)); 1038 EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename( 1039 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg)); 1040} 1041 1042// Verify the dexopt status values from dalvik.system.DexFile 1043// match the OatFileAssistant::DexOptStatus values. 1044TEST_F(OatFileAssistantTest, DexOptStatusValues) { 1045 ScopedObjectAccess soa(Thread::Current()); 1046 StackHandleScope<1> hs(soa.Self()); 1047 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 1048 Handle<mirror::Class> dexfile( 1049 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;"))); 1050 ASSERT_FALSE(dexfile.Get() == nullptr); 1051 linker->EnsureInitialized(soa.Self(), dexfile, true, true); 1052 1053 ArtField* no_dexopt_needed = mirror::Class::FindStaticField( 1054 soa.Self(), dexfile, "NO_DEXOPT_NEEDED", "I"); 1055 ASSERT_FALSE(no_dexopt_needed == nullptr); 1056 EXPECT_EQ(no_dexopt_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1057 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, no_dexopt_needed->GetInt(dexfile.Get())); 1058 1059 ArtField* dex2oat_needed = mirror::Class::FindStaticField( 1060 soa.Self(), dexfile, "DEX2OAT_NEEDED", "I"); 1061 ASSERT_FALSE(dex2oat_needed == nullptr); 1062 EXPECT_EQ(dex2oat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1063 EXPECT_EQ(OatFileAssistant::kDex2OatNeeded, dex2oat_needed->GetInt(dexfile.Get())); 1064 1065 ArtField* patchoat_needed = mirror::Class::FindStaticField( 1066 soa.Self(), dexfile, "PATCHOAT_NEEDED", "I"); 1067 ASSERT_FALSE(patchoat_needed == nullptr); 1068 EXPECT_EQ(patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1069 EXPECT_EQ(OatFileAssistant::kPatchOatNeeded, patchoat_needed->GetInt(dexfile.Get())); 1070 1071 ArtField* self_patchoat_needed = mirror::Class::FindStaticField( 1072 soa.Self(), dexfile, "SELF_PATCHOAT_NEEDED", "I"); 1073 ASSERT_FALSE(self_patchoat_needed == nullptr); 1074 EXPECT_EQ(self_patchoat_needed->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1075 EXPECT_EQ(OatFileAssistant::kSelfPatchOatNeeded, self_patchoat_needed->GetInt(dexfile.Get())); 1076} 1077 1078// TODO: More Tests: 1079// * Test class linker falls back to unquickened dex for DexNoOat 1080// * Test class linker falls back to unquickened dex for MultiDexNoOat 1081// * Test using secondary isa 1082// * Test with profiling info? 1083// * Test for status of oat while oat is being generated (how?) 1084// * Test case where 32 and 64 bit boot class paths differ, 1085// and we ask IsInBootClassPath for a class in exactly one of the 32 or 1086// 64 bit boot class paths. 1087// * Test unexpected scenarios (?): 1088// - Dex is stripped, don't have odex. 1089// - Oat file corrupted after status check, before reload unexecutable 1090// because it's unrelocated and no dex2oat 1091 1092} // namespace art 1093