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 <string> 18 #include <vector> 19 #include <sys/param.h> 20 21 #include "android-base/strings.h" 22 #include <gtest/gtest.h> 23 24 #include "art_field-inl.h" 25 #include "class_linker-inl.h" 26 #include "class_loader_context.h" 27 #include "common_runtime_test.h" 28 #include "dexopt_test.h" 29 #include "oat_file.h" 30 #include "oat_file_manager.h" 31 #include "os.h" 32 #include "scoped_thread_state_change-inl.h" 33 #include "thread-current-inl.h" 34 #include "utils.h" 35 36 namespace art { 37 38 static const std::string kSpecialSharedLibrary = "&"; 39 static ClassLoaderContext* kSpecialSharedLibraryContext = nullptr; 40 41 class OatFileAssistantTest : public DexoptTest {}; 42 43 class OatFileAssistantNoDex2OatTest : public DexoptTest { 44 public: 45 virtual void SetUpRuntimeOptions(RuntimeOptions* options) { 46 DexoptTest::SetUpRuntimeOptions(options); 47 options->push_back(std::make_pair("-Xnodex2oat", nullptr)); 48 } 49 }; 50 51 class ScopedNonWritable { 52 public: 53 explicit ScopedNonWritable(const std::string& dex_location) { 54 is_valid_ = false; 55 size_t pos = dex_location.rfind('/'); 56 if (pos != std::string::npos) { 57 is_valid_ = true; 58 dex_parent_ = dex_location.substr(0, pos); 59 if (chmod(dex_parent_.c_str(), 0555) != 0) { 60 PLOG(ERROR) << "Could not change permissions on " << dex_parent_; 61 } 62 } 63 } 64 65 bool IsSuccessful() { return is_valid_ && (access(dex_parent_.c_str(), W_OK) != 0); } 66 67 ~ScopedNonWritable() { 68 if (is_valid_) { 69 if (chmod(dex_parent_.c_str(), 0777) != 0) { 70 PLOG(ERROR) << "Could not restore permissions on " << dex_parent_; 71 } 72 } 73 } 74 75 private: 76 std::string dex_parent_; 77 bool is_valid_; 78 }; 79 80 static bool IsExecutedAsRoot() { 81 return geteuid() == 0; 82 } 83 84 // Case: We have a DEX file, but no OAT file for it. 85 // Expect: The status is kDex2OatNeeded. 86 TEST_F(OatFileAssistantTest, DexNoOat) { 87 std::string dex_location = GetScratchDir() + "/DexNoOat.jar"; 88 Copy(GetDexSrc1(), dex_location); 89 90 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 91 92 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 93 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 94 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 95 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 96 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 97 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile)); 98 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 99 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 100 101 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 102 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 103 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 104 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 105 } 106 107 // Case: We have no DEX file and no OAT file. 108 // Expect: Status is kNoDexOptNeeded. Loading should fail, but not crash. 109 TEST_F(OatFileAssistantTest, NoDexNoOat) { 110 std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar"; 111 112 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 113 114 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 115 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 116 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 117 118 // Trying to make the oat file up to date should not fail or crash. 119 std::string error_msg; 120 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 121 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)); 122 123 // Trying to get the best oat file should fail, but not crash. 124 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 125 EXPECT_EQ(nullptr, oat_file.get()); 126 } 127 128 // Case: We have a DEX file and a PIC ODEX file, but no OAT file. 129 // Expect: The status is kNoDexOptNeeded, because PIC needs no relocation. 130 TEST_F(OatFileAssistantTest, OdexUpToDate) { 131 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar"; 132 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex"; 133 Copy(GetDexSrc1(), dex_location); 134 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 135 136 // For the use of oat location by making the dex parent not writable. 137 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 138 139 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 140 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 141 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 142 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 143 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 144 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 145 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, 146 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 147 148 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 149 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus()); 150 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 151 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 152 } 153 154 // Case: We have a DEX file and a PIC ODEX file, but no OAT file. We load the dex 155 // file via a symlink. 156 // Expect: The status is kNoDexOptNeeded, because PIC needs no relocation. 157 TEST_F(OatFileAssistantTest, OdexUpToDateSymLink) { 158 std::string scratch_dir = GetScratchDir(); 159 std::string dex_location = GetScratchDir() + "/OdexUpToDate.jar"; 160 std::string odex_location = GetOdexDir() + "/OdexUpToDate.odex"; 161 162 Copy(GetDexSrc1(), dex_location); 163 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 164 165 // Now replace the dex location with a symlink. 166 std::string link = scratch_dir + "/link"; 167 ASSERT_EQ(0, symlink(scratch_dir.c_str(), link.c_str())); 168 dex_location = link + "/OdexUpToDate.jar"; 169 170 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 171 172 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 173 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 174 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 175 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 176 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 177 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 178 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, 179 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 180 181 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 182 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus()); 183 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 184 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 185 } 186 187 // Case: We have a DEX file and up-to-date OAT file for it. 188 // Expect: The status is kNoDexOptNeeded. 189 TEST_F(OatFileAssistantTest, OatUpToDate) { 190 if (IsExecutedAsRoot()) { 191 // We cannot simulate non writable locations when executed as root: b/38000545. 192 LOG(ERROR) << "Test skipped because it's running as root"; 193 return; 194 } 195 196 std::string dex_location = GetScratchDir() + "/OatUpToDate.jar"; 197 Copy(GetDexSrc1(), dex_location); 198 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 199 200 // For the use of oat location by making the dex parent not writable. 201 ScopedNonWritable scoped_non_writable(dex_location); 202 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 203 204 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 205 206 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 207 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 208 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 209 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 210 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 211 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 212 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, 213 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 214 215 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 216 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 217 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus()); 218 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 219 } 220 221 // Case: We have a DEX file and up-to-date OAT file for it. We load the dex file 222 // via a symlink. 223 // Expect: The status is kNoDexOptNeeded. 224 TEST_F(OatFileAssistantTest, OatUpToDateSymLink) { 225 if (IsExecutedAsRoot()) { 226 // We cannot simulate non writable locations when executed as root: b/38000545. 227 LOG(ERROR) << "Test skipped because it's running as root"; 228 return; 229 } 230 231 std::string real = GetScratchDir() + "/real"; 232 ASSERT_EQ(0, mkdir(real.c_str(), 0700)); 233 std::string link = GetScratchDir() + "/link"; 234 ASSERT_EQ(0, symlink(real.c_str(), link.c_str())); 235 236 std::string dex_location = real + "/OatUpToDate.jar"; 237 238 Copy(GetDexSrc1(), dex_location); 239 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 240 241 // Update the dex location to point to the symlink. 242 dex_location = link + "/OatUpToDate.jar"; 243 244 // For the use of oat location by making the dex parent not writable. 245 ScopedNonWritable scoped_non_writable(dex_location); 246 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 247 248 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 249 250 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 251 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 252 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 253 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 254 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 255 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 256 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, 257 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 258 259 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 260 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 261 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus()); 262 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 263 } 264 265 // Case: We have a DEX file and up-to-date (ODEX) VDEX file for it, but no 266 // ODEX file. 267 TEST_F(OatFileAssistantTest, VdexUpToDateNoOdex) { 268 // This test case is only meaningful if vdex is enabled. 269 if (!kIsVdexEnabled) { 270 return; 271 } 272 273 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOdex.jar"; 274 std::string odex_location = GetOdexDir() + "/VdexUpToDateNoOdex.oat"; 275 276 Copy(GetDexSrc1(), dex_location); 277 278 // Generating and deleting the oat file should have the side effect of 279 // creating an up-to-date vdex file. 280 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 281 ASSERT_EQ(0, unlink(odex_location.c_str())); 282 283 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 284 285 // Even though the vdex file is up to date, because we don't have the oat 286 // file, we can't know that the vdex depends on the boot image and is up to 287 // date with respect to the boot image. Instead we must assume the vdex file 288 // depends on the boot image and is out of date with respect to the boot 289 // image. 290 EXPECT_EQ(-OatFileAssistant::kDex2OatForBootImage, 291 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 292 293 // Make sure we don't crash in this case when we dump the status. We don't 294 // care what the actual dumped value is. 295 oat_file_assistant.GetStatusDump(); 296 } 297 298 // Case: We have a DEX file and empty VDEX and ODEX files. 299 TEST_F(OatFileAssistantTest, EmptyVdexOdex) { 300 std::string dex_location = GetScratchDir() + "/EmptyVdexOdex.jar"; 301 std::string odex_location = GetOdexDir() + "/EmptyVdexOdex.oat"; 302 std::string vdex_location = GetOdexDir() + "/EmptyVdexOdex.vdex"; 303 304 Copy(GetDexSrc1(), dex_location); 305 ScratchFile vdex_file(vdex_location.c_str()); 306 ScratchFile odex_file(odex_location.c_str()); 307 308 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 309 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 310 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 311 } 312 313 // Case: We have a DEX file and up-to-date (OAT) VDEX file for it, but no OAT 314 // file. 315 TEST_F(OatFileAssistantTest, VdexUpToDateNoOat) { 316 // This test case is only meaningful if vdex is enabled. 317 if (!kIsVdexEnabled) { 318 return; 319 } 320 if (IsExecutedAsRoot()) { 321 // We cannot simulate non writable locations when executed as root: b/38000545. 322 LOG(ERROR) << "Test skipped because it's running as root"; 323 return; 324 } 325 326 std::string dex_location = GetScratchDir() + "/VdexUpToDateNoOat.jar"; 327 std::string oat_location; 328 std::string error_msg; 329 ASSERT_TRUE(OatFileAssistant::DexLocationToOatFilename( 330 dex_location, kRuntimeISA, &oat_location, &error_msg)) << error_msg; 331 332 Copy(GetDexSrc1(), dex_location); 333 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 334 ASSERT_EQ(0, unlink(oat_location.c_str())); 335 336 ScopedNonWritable scoped_non_writable(dex_location); 337 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 338 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 339 340 // Even though the vdex file is up to date, because we don't have the oat 341 // file, we can't know that the vdex depends on the boot image and is up to 342 // date with respect to the boot image. Instead we must assume the vdex file 343 // depends on the boot image and is out of date with respect to the boot 344 // image. 345 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, 346 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 347 } 348 349 // Case: We have a DEX file and speed-profile OAT file for it. 350 // Expect: The status is kNoDexOptNeeded if the profile hasn't changed, but 351 // kDex2Oat if the profile has changed. 352 TEST_F(OatFileAssistantTest, ProfileOatUpToDate) { 353 if (IsExecutedAsRoot()) { 354 // We cannot simulate non writable locations when executed as root: b/38000545. 355 LOG(ERROR) << "Test skipped because it's running as root"; 356 return; 357 } 358 359 std::string dex_location = GetScratchDir() + "/ProfileOatUpToDate.jar"; 360 Copy(GetDexSrc1(), dex_location); 361 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile); 362 363 ScopedNonWritable scoped_non_writable(dex_location); 364 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 365 366 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 367 368 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 369 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false)); 370 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 371 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false)); 372 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, 373 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true)); 374 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, 375 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true)); 376 377 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 378 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 379 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus()); 380 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 381 } 382 383 // Case: We have a MultiDEX file and up-to-date OAT file for it. 384 // Expect: The status is kNoDexOptNeeded and we load all dex files. 385 TEST_F(OatFileAssistantTest, MultiDexOatUpToDate) { 386 if (IsExecutedAsRoot()) { 387 // We cannot simulate non writable locations when executed as root: b/38000545. 388 LOG(ERROR) << "Test skipped because it's running as root"; 389 return; 390 } 391 392 std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar"; 393 Copy(GetMultiDexSrc1(), dex_location); 394 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 395 396 ScopedNonWritable scoped_non_writable(dex_location); 397 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 398 399 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 400 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 401 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false)); 402 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 403 404 // Verify we can load both dex files. 405 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 406 ASSERT_TRUE(oat_file.get() != nullptr); 407 EXPECT_TRUE(oat_file->IsExecutable()); 408 std::vector<std::unique_ptr<const DexFile>> dex_files; 409 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 410 EXPECT_EQ(2u, dex_files.size()); 411 } 412 413 // Case: We have a MultiDEX file where the non-main multdex entry is out of date. 414 // Expect: The status is kDex2OatNeeded. 415 TEST_F(OatFileAssistantTest, MultiDexNonMainOutOfDate) { 416 if (IsExecutedAsRoot()) { 417 // We cannot simulate non writable locations when executed as root: b/38000545. 418 LOG(ERROR) << "Test skipped because it's running as root"; 419 return; 420 } 421 422 std::string dex_location = GetScratchDir() + "/MultiDexNonMainOutOfDate.jar"; 423 424 // Compile code for GetMultiDexSrc1. 425 Copy(GetMultiDexSrc1(), dex_location); 426 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 427 428 // Now overwrite the dex file with GetMultiDexSrc2 so the non-main checksum 429 // is out of date. 430 Copy(GetMultiDexSrc2(), dex_location); 431 432 ScopedNonWritable scoped_non_writable(dex_location); 433 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 434 435 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 436 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 437 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed, false)); 438 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 439 } 440 441 // Case: We have a stripped MultiDEX file where the non-main multidex entry is 442 // out of date with respect to the odex file. 443 TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) { 444 std::string dex_location = GetScratchDir() + "/StrippedMultiDexNonMainOutOfDate.jar"; 445 std::string odex_location = GetOdexDir() + "/StrippedMultiDexNonMainOutOfDate.odex"; 446 447 // Compile the oat from GetMultiDexSrc1. 448 Copy(GetMultiDexSrc1(), dex_location); 449 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 450 451 // Compile the odex from GetMultiDexSrc2, which has a different non-main 452 // dex checksum. 453 Copy(GetMultiDexSrc2(), dex_location); 454 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken); 455 456 // Strip the dex file. 457 Copy(GetStrippedDexSrc1(), dex_location); 458 459 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, /*load_executable*/false); 460 461 // Because the dex file is stripped, the odex file is considered the source 462 // of truth for the dex checksums. The oat file should be considered 463 // unusable. 464 std::unique_ptr<OatFile> best_file = oat_file_assistant.GetBestOatFile(); 465 ASSERT_TRUE(best_file.get() != nullptr); 466 EXPECT_EQ(best_file->GetLocation(), odex_location); 467 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 468 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus()); 469 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus()); 470 } 471 472 // Case: We have a MultiDEX file and up-to-date ODEX file for it with relative 473 // encoded dex locations. 474 // Expect: The oat file status is kNoDexOptNeeded. 475 TEST_F(OatFileAssistantTest, RelativeEncodedDexLocation) { 476 std::string dex_location = GetScratchDir() + "/RelativeEncodedDexLocation.jar"; 477 std::string odex_location = GetOdexDir() + "/RelativeEncodedDexLocation.odex"; 478 479 // Create the dex file 480 Copy(GetMultiDexSrc1(), dex_location); 481 482 // Create the oat file with relative encoded dex location. 483 std::vector<std::string> args; 484 args.push_back("--dex-file=" + dex_location); 485 args.push_back("--dex-location=" + std::string("RelativeEncodedDexLocation.jar")); 486 args.push_back("--oat-file=" + odex_location); 487 args.push_back("--compiler-filter=speed"); 488 489 std::string error_msg; 490 ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg; 491 492 // Verify we can load both dex files. 493 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 494 495 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 496 ASSERT_TRUE(oat_file.get() != nullptr); 497 EXPECT_TRUE(oat_file->IsExecutable()); 498 std::vector<std::unique_ptr<const DexFile>> dex_files; 499 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 500 EXPECT_EQ(2u, dex_files.size()); 501 } 502 503 // Case: We have a DEX file and an OAT file out of date with respect to the 504 // dex checksum. 505 TEST_F(OatFileAssistantTest, OatDexOutOfDate) { 506 if (IsExecutedAsRoot()) { 507 // We cannot simulate non writable locations when executed as root: b/38000545. 508 LOG(ERROR) << "Test skipped because it's running as root"; 509 return; 510 } 511 512 std::string dex_location = GetScratchDir() + "/OatDexOutOfDate.jar"; 513 514 // We create a dex, generate an oat for it, then overwrite the dex with a 515 // different dex to make the oat out of date. 516 Copy(GetDexSrc1(), dex_location); 517 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 518 Copy(GetDexSrc2(), dex_location); 519 520 ScopedNonWritable scoped_non_writable(dex_location); 521 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 522 523 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 524 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 525 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 526 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 527 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 528 529 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 530 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 531 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus()); 532 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 533 } 534 535 // Case: We have a DEX file and an (ODEX) VDEX file out of date with respect 536 // to the dex checksum, but no ODEX file. 537 TEST_F(OatFileAssistantTest, VdexDexOutOfDate) { 538 // This test case is only meaningful if vdex is enabled. 539 if (!kIsVdexEnabled) { 540 return; 541 } 542 543 std::string dex_location = GetScratchDir() + "/VdexDexOutOfDate.jar"; 544 std::string odex_location = GetOdexDir() + "/VdexDexOutOfDate.oat"; 545 546 Copy(GetDexSrc1(), dex_location); 547 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 548 ASSERT_EQ(0, unlink(odex_location.c_str())); 549 Copy(GetDexSrc2(), dex_location); 550 551 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 552 553 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 554 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 555 } 556 557 // Case: We have a MultiDEX (ODEX) VDEX file where the non-main multidex entry 558 // is out of date and there is no corresponding ODEX file. 559 TEST_F(OatFileAssistantTest, VdexMultiDexNonMainOutOfDate) { 560 // This test case is only meaningful if vdex is enabled. 561 if (!kIsVdexEnabled) { 562 return; 563 } 564 565 std::string dex_location = GetScratchDir() + "/VdexMultiDexNonMainOutOfDate.jar"; 566 std::string odex_location = GetOdexDir() + "/VdexMultiDexNonMainOutOfDate.odex"; 567 568 Copy(GetMultiDexSrc1(), dex_location); 569 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 570 ASSERT_EQ(0, unlink(odex_location.c_str())); 571 Copy(GetMultiDexSrc2(), dex_location); 572 573 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 574 575 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 576 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 577 } 578 579 // Case: We have a DEX file and an OAT file out of date with respect to the 580 // boot image. 581 TEST_F(OatFileAssistantTest, OatImageOutOfDate) { 582 if (IsExecutedAsRoot()) { 583 // We cannot simulate non writable locations when executed as root: b/38000545. 584 LOG(ERROR) << "Test skipped because it's running as root"; 585 return; 586 } 587 588 std::string dex_location = GetScratchDir() + "/OatImageOutOfDate.jar"; 589 590 Copy(GetDexSrc1(), dex_location); 591 GenerateOatForTest(dex_location.c_str(), 592 CompilerFilter::kSpeed, 593 /*relocate*/true, 594 /*pic*/false, 595 /*with_alternate_image*/true); 596 597 ScopedNonWritable scoped_non_writable(dex_location); 598 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 599 600 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 601 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, 602 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 603 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, 604 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 605 EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, 606 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 607 608 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 609 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 610 EXPECT_EQ(OatFileAssistant::kOatBootImageOutOfDate, oat_file_assistant.OatFileStatus()); 611 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 612 } 613 614 // Case: We have a DEX file and a verify-at-runtime OAT file out of date with 615 // respect to the boot image. 616 // It shouldn't matter that the OAT file is out of date, because it is 617 // verify-at-runtime. 618 TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) { 619 if (IsExecutedAsRoot()) { 620 // We cannot simulate non writable locations when executed as root: b/38000545. 621 LOG(ERROR) << "Test skipped because it's running as root"; 622 return; 623 } 624 625 std::string dex_location = GetScratchDir() + "/OatVerifyAtRuntimeImageOutOfDate.jar"; 626 627 Copy(GetDexSrc1(), dex_location); 628 GenerateOatForTest(dex_location.c_str(), 629 CompilerFilter::kExtract, 630 /*relocate*/true, 631 /*pic*/false, 632 /*with_alternate_image*/true); 633 634 ScopedNonWritable scoped_non_writable(dex_location); 635 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 636 637 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 638 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 639 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 640 EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, 641 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 642 643 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 644 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 645 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OatFileStatus()); 646 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 647 } 648 649 // Case: We have a DEX file and an ODEX file, but no OAT file. 650 TEST_F(OatFileAssistantTest, DexOdexNoOat) { 651 std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar"; 652 std::string odex_location = GetOdexDir() + "/DexOdexNoOat.odex"; 653 654 // Create the dex and odex files 655 Copy(GetDexSrc1(), dex_location); 656 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 657 658 // Verify the status. 659 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 660 661 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 662 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 663 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation, 664 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 665 666 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 667 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus()); 668 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 669 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 670 671 // We should still be able to get the non-executable odex file to run from. 672 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 673 ASSERT_TRUE(oat_file.get() != nullptr); 674 } 675 676 // Case: We have a stripped DEX file and a PIC ODEX file, but no OAT file. 677 TEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) { 678 std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar"; 679 std::string odex_location = GetOdexDir() + "/StrippedDexOdexNoOat.odex"; 680 681 // Create the dex and odex files 682 Copy(GetDexSrc1(), dex_location); 683 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 684 685 // Strip the dex file 686 Copy(GetStrippedDexSrc1(), dex_location); 687 688 // Verify the status. 689 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 690 691 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 692 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 693 694 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 695 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus()); 696 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 697 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 698 699 // Verify we can load the dex files from it. 700 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 701 ASSERT_TRUE(oat_file.get() != nullptr); 702 EXPECT_TRUE(oat_file->IsExecutable()); 703 std::vector<std::unique_ptr<const DexFile>> dex_files; 704 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 705 EXPECT_EQ(1u, dex_files.size()); 706 } 707 708 // Case: We have a stripped DEX file, a PIC ODEX file, and an out-of-date OAT file. 709 TEST_F(OatFileAssistantTest, StrippedDexOdexOat) { 710 std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar"; 711 std::string odex_location = GetOdexDir() + "/StrippedDexOdexOat.odex"; 712 713 // Create the oat file from a different dex file so it looks out of date. 714 Copy(GetDexSrc2(), dex_location); 715 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 716 717 // Create the odex file 718 Copy(GetDexSrc1(), dex_location); 719 GeneratePicOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 720 721 // Strip the dex file. 722 Copy(GetStrippedDexSrc1(), dex_location); 723 724 // Verify the status. 725 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 726 727 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 728 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 729 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 730 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 731 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, // Compiling from the .vdex file 732 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); 733 734 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 735 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus()); 736 EXPECT_EQ(OatFileAssistant::kOatDexOutOfDate, oat_file_assistant.OatFileStatus()); 737 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 738 739 // Verify we can load the dex files from it. 740 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 741 ASSERT_TRUE(oat_file.get() != nullptr); 742 EXPECT_TRUE(oat_file->IsExecutable()); 743 std::vector<std::unique_ptr<const DexFile>> dex_files; 744 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 745 EXPECT_EQ(1u, dex_files.size()); 746 } 747 748 // Case: We have a stripped (or resource-only) DEX file, no ODEX file and no 749 // OAT file. Expect: The status is kNoDexOptNeeded. 750 TEST_F(OatFileAssistantTest, ResourceOnlyDex) { 751 std::string dex_location = GetScratchDir() + "/ResourceOnlyDex.jar"; 752 753 Copy(GetStrippedDexSrc1(), dex_location); 754 755 // Verify the status. 756 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 757 758 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 759 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 760 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 761 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 762 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 763 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 764 765 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 766 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 767 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 768 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 769 770 // Make the oat file up to date. This should have no effect. 771 std::string error_msg; 772 Runtime::Current()->AddCompilerOption("--compiler-filter=speed"); 773 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 774 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) << 775 error_msg; 776 777 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 778 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 779 780 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 781 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 782 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 783 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 784 } 785 786 // Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and 787 // OAT files both have patch delta of 0. 788 // Expect: It shouldn't crash. 789 TEST_F(OatFileAssistantTest, OdexOatOverlap) { 790 std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar"; 791 std::string odex_location = GetOdexDir() + "/OdexOatOverlap.odex"; 792 793 // Create the dex, the odex and the oat files. 794 Copy(GetDexSrc1(), dex_location); 795 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 796 GenerateOatForTest(dex_location.c_str(), 797 CompilerFilter::kSpeed, 798 /*relocate*/false, 799 /*pic*/false, 800 /*with_alternate_image*/false); 801 802 // Verify things don't go bad. 803 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 804 805 // -kDex2OatForRelocation is expected rather than kDex2OatForRelocation 806 // based on the assumption that the odex location is more up-to-date than the oat 807 // location, even if they both need relocation. 808 EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation, 809 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 810 811 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 812 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OdexFileStatus()); 813 EXPECT_EQ(OatFileAssistant::kOatRelocationOutOfDate, oat_file_assistant.OatFileStatus()); 814 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 815 816 // Things aren't relocated, so it should fall back to interpreted. 817 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 818 ASSERT_TRUE(oat_file.get() != nullptr); 819 820 EXPECT_FALSE(oat_file->IsExecutable()); 821 std::vector<std::unique_ptr<const DexFile>> dex_files; 822 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 823 EXPECT_EQ(1u, dex_files.size()); 824 } 825 826 // Case: We have a DEX file and a VerifyAtRuntime ODEX file, but no OAT file. 827 // Expect: The status is kNoDexOptNeeded, because VerifyAtRuntime contains no code. 828 TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) { 829 std::string dex_location = GetScratchDir() + "/DexVerifyAtRuntimeOdexNoOat.jar"; 830 std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex"; 831 832 // Create the dex and odex files 833 Copy(GetDexSrc1(), dex_location); 834 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract); 835 836 // Verify the status. 837 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 838 839 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 840 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); 841 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, 842 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 843 844 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 845 EXPECT_EQ(OatFileAssistant::kOatUpToDate, oat_file_assistant.OdexFileStatus()); 846 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 847 EXPECT_TRUE(oat_file_assistant.HasOriginalDexFiles()); 848 } 849 850 // Case: We have a DEX file and up-to-date OAT file for it. 851 // Expect: We should load an executable dex file. 852 TEST_F(OatFileAssistantTest, LoadOatUpToDate) { 853 if (IsExecutedAsRoot()) { 854 // We cannot simulate non writable locations when executed as root: b/38000545. 855 LOG(ERROR) << "Test skipped because it's running as root"; 856 return; 857 } 858 859 std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar"; 860 861 Copy(GetDexSrc1(), dex_location); 862 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 863 864 ScopedNonWritable scoped_non_writable(dex_location); 865 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 866 867 // Load the oat using an oat file assistant. 868 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 869 870 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 871 ASSERT_TRUE(oat_file.get() != nullptr); 872 EXPECT_TRUE(oat_file->IsExecutable()); 873 std::vector<std::unique_ptr<const DexFile>> dex_files; 874 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 875 EXPECT_EQ(1u, dex_files.size()); 876 } 877 878 // Case: We have a DEX file and up-to-date quicken OAT file for it. 879 // Expect: We should still load the oat file as executable. 880 TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) { 881 if (IsExecutedAsRoot()) { 882 // We cannot simulate non writable locations when executed as root: b/38000545. 883 LOG(ERROR) << "Test skipped because it's running as root"; 884 return; 885 } 886 887 std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar"; 888 889 Copy(GetDexSrc1(), dex_location); 890 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken); 891 892 ScopedNonWritable scoped_non_writable(dex_location); 893 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 894 895 // Load the oat using an oat file assistant. 896 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 897 898 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 899 ASSERT_TRUE(oat_file.get() != nullptr); 900 EXPECT_TRUE(oat_file->IsExecutable()); 901 std::vector<std::unique_ptr<const DexFile>> dex_files; 902 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 903 EXPECT_EQ(1u, dex_files.size()); 904 } 905 906 // Case: We have a DEX file and up-to-date OAT file for it. 907 // Expect: Loading non-executable should load the oat non-executable. 908 TEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) { 909 if (IsExecutedAsRoot()) { 910 // We cannot simulate non writable locations when executed as root: b/38000545. 911 LOG(ERROR) << "Test skipped because it's running as root"; 912 return; 913 } 914 915 std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar"; 916 917 Copy(GetDexSrc1(), dex_location); 918 919 ScopedNonWritable scoped_non_writable(dex_location); 920 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 921 922 GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); 923 924 // Load the oat using an oat file assistant. 925 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 926 927 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 928 ASSERT_TRUE(oat_file.get() != nullptr); 929 EXPECT_FALSE(oat_file->IsExecutable()); 930 std::vector<std::unique_ptr<const DexFile>> dex_files; 931 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 932 EXPECT_EQ(1u, dex_files.size()); 933 } 934 935 // Case: We don't have a DEX file and can't write the oat file. 936 // Expect: We should fail to generate the oat file without crashing. 937 TEST_F(OatFileAssistantTest, GenNoDex) { 938 if (IsExecutedAsRoot()) { 939 // We cannot simulate non writable locations when executed as root: b/38000545. 940 LOG(ERROR) << "Test skipped because it's running as root"; 941 return; 942 } 943 944 std::string dex_location = GetScratchDir() + "/GenNoDex.jar"; 945 946 ScopedNonWritable scoped_non_writable(dex_location); 947 ASSERT_TRUE(scoped_non_writable.IsSuccessful()); 948 949 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 950 std::string error_msg; 951 Runtime::Current()->AddCompilerOption("--compiler-filter=speed"); 952 // We should get kUpdateSucceeded from MakeUpToDate since there's nothing 953 // that can be done in this situation. 954 ASSERT_EQ(OatFileAssistant::kUpdateSucceeded, 955 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)); 956 957 // Verify it didn't create an oat in the default location (dalvik-cache). 958 OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false); 959 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OatFileStatus()); 960 // Verify it didn't create the odex file in the default location (../oat/isa/...odex) 961 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, ofm.OdexFileStatus()); 962 } 963 964 // Turn an absolute path into a path relative to the current working 965 // directory. 966 static std::string MakePathRelative(const std::string& target) { 967 char buf[MAXPATHLEN]; 968 std::string cwd = getcwd(buf, MAXPATHLEN); 969 970 // Split the target and cwd paths into components. 971 std::vector<std::string> target_path; 972 std::vector<std::string> cwd_path; 973 Split(target, '/', &target_path); 974 Split(cwd, '/', &cwd_path); 975 976 // Reverse the path components, so we can use pop_back(). 977 std::reverse(target_path.begin(), target_path.end()); 978 std::reverse(cwd_path.begin(), cwd_path.end()); 979 980 // Drop the common prefix of the paths. Because we reversed the path 981 // components, this becomes the common suffix of target_path and cwd_path. 982 while (!target_path.empty() && !cwd_path.empty() 983 && target_path.back() == cwd_path.back()) { 984 target_path.pop_back(); 985 cwd_path.pop_back(); 986 } 987 988 // For each element of the remaining cwd_path, add '..' to the beginning 989 // of the target path. Because we reversed the path components, we add to 990 // the end of target_path. 991 for (unsigned int i = 0; i < cwd_path.size(); i++) { 992 target_path.push_back(".."); 993 } 994 995 // Reverse again to get the right path order, and join to get the result. 996 std::reverse(target_path.begin(), target_path.end()); 997 return android::base::Join(target_path, '/'); 998 } 999 1000 // Case: Non-absolute path to Dex location. 1001 // Expect: Not sure, but it shouldn't crash. 1002 TEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) { 1003 std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar"; 1004 Copy(GetDexSrc1(), abs_dex_location); 1005 1006 std::string dex_location = MakePathRelative(abs_dex_location); 1007 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 1008 1009 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 1010 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 1011 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 1012 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 1013 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 1014 } 1015 1016 // Case: Very short, non-existent Dex location. 1017 // Expect: kNoDexOptNeeded. 1018 TEST_F(OatFileAssistantTest, ShortDexLocation) { 1019 std::string dex_location = "/xx"; 1020 1021 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 1022 1023 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 1024 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 1025 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 1026 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 1027 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 1028 EXPECT_FALSE(oat_file_assistant.HasOriginalDexFiles()); 1029 1030 // Trying to make it up to date should have no effect. 1031 std::string error_msg; 1032 Runtime::Current()->AddCompilerOption("--compiler-filter=speed"); 1033 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 1034 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)); 1035 EXPECT_TRUE(error_msg.empty()); 1036 } 1037 1038 // Case: Non-standard extension for dex file. 1039 // Expect: The status is kDex2OatNeeded. 1040 TEST_F(OatFileAssistantTest, LongDexExtension) { 1041 std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx"; 1042 Copy(GetDexSrc1(), dex_location); 1043 1044 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 1045 1046 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 1047 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 1048 1049 EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); 1050 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); 1051 EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OatFileStatus()); 1052 } 1053 1054 // A task to generate a dex location. Used by the RaceToGenerate test. 1055 class RaceGenerateTask : public Task { 1056 public: 1057 explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location) 1058 : dex_location_(dex_location), oat_location_(oat_location), loaded_oat_file_(nullptr) 1059 {} 1060 1061 void Run(Thread* self ATTRIBUTE_UNUSED) { 1062 // Load the dex files, and save a pointer to the loaded oat file, so that 1063 // we can verify only one oat file was loaded for the dex location. 1064 std::vector<std::unique_ptr<const DexFile>> dex_files; 1065 std::vector<std::string> error_msgs; 1066 const OatFile* oat_file = nullptr; 1067 dex_files = Runtime::Current()->GetOatFileManager().OpenDexFilesFromOat( 1068 dex_location_.c_str(), 1069 Runtime::Current()->GetSystemClassLoader(), 1070 /*dex_elements*/nullptr, 1071 &oat_file, 1072 &error_msgs); 1073 CHECK(!dex_files.empty()) << android::base::Join(error_msgs, '\n'); 1074 CHECK(dex_files[0]->GetOatDexFile() != nullptr) << dex_files[0]->GetLocation(); 1075 loaded_oat_file_ = dex_files[0]->GetOatDexFile()->GetOatFile(); 1076 CHECK_EQ(loaded_oat_file_, oat_file); 1077 } 1078 1079 const OatFile* GetLoadedOatFile() const { 1080 return loaded_oat_file_; 1081 } 1082 1083 private: 1084 std::string dex_location_; 1085 std::string oat_location_; 1086 const OatFile* loaded_oat_file_; 1087 }; 1088 1089 // Test the case where multiple processes race to generate an oat file. 1090 // This simulates multiple processes using multiple threads. 1091 // 1092 // We want unique Oat files to be loaded even when there is a race to load. 1093 // TODO: The test case no longer tests locking the way it was intended since we now get multiple 1094 // copies of the same Oat files mapped at different locations. 1095 TEST_F(OatFileAssistantTest, RaceToGenerate) { 1096 std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar"; 1097 std::string oat_location = GetOdexDir() + "/RaceToGenerate.oat"; 1098 1099 // Start the runtime to initialize the system's class loader. 1100 Thread::Current()->TransitionFromSuspendedToRunnable(); 1101 runtime_->Start(); 1102 1103 // We use the lib core dex file, because it's large, and hopefully should 1104 // take a while to generate. 1105 Copy(GetLibCoreDexFileNames()[0], dex_location); 1106 1107 const int kNumThreads = 32; 1108 Thread* self = Thread::Current(); 1109 ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads); 1110 std::vector<std::unique_ptr<RaceGenerateTask>> tasks; 1111 for (int i = 0; i < kNumThreads; i++) { 1112 std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location)); 1113 thread_pool.AddTask(self, task.get()); 1114 tasks.push_back(std::move(task)); 1115 } 1116 thread_pool.StartWorkers(self); 1117 thread_pool.Wait(self, true, false); 1118 1119 // Verify every task got a unique oat file. 1120 std::set<const OatFile*> oat_files; 1121 for (auto& task : tasks) { 1122 const OatFile* oat_file = task->GetLoadedOatFile(); 1123 EXPECT_TRUE(oat_files.find(oat_file) == oat_files.end()); 1124 oat_files.insert(oat_file); 1125 } 1126 } 1127 1128 // Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is 1129 // disabled. 1130 // Expect: We should load the odex file non-executable. 1131 TEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) { 1132 std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar"; 1133 std::string odex_location = GetOdexDir() + "/LoadDexOdexNoOat.odex"; 1134 1135 // Create the dex and odex files 1136 Copy(GetDexSrc1(), dex_location); 1137 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 1138 1139 // Load the oat using an executable oat file assistant. 1140 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 1141 1142 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1143 ASSERT_TRUE(oat_file.get() != nullptr); 1144 EXPECT_FALSE(oat_file->IsExecutable()); 1145 std::vector<std::unique_ptr<const DexFile>> dex_files; 1146 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 1147 EXPECT_EQ(1u, dex_files.size()); 1148 } 1149 1150 // Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is 1151 // disabled. 1152 // Expect: We should load the odex file non-executable. 1153 TEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) { 1154 std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar"; 1155 std::string odex_location = GetOdexDir() + "/LoadMultiDexOdexNoOat.odex"; 1156 1157 // Create the dex and odex files 1158 Copy(GetMultiDexSrc1(), dex_location); 1159 GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); 1160 1161 // Load the oat using an executable oat file assistant. 1162 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); 1163 1164 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1165 ASSERT_TRUE(oat_file.get() != nullptr); 1166 EXPECT_FALSE(oat_file->IsExecutable()); 1167 std::vector<std::unique_ptr<const DexFile>> dex_files; 1168 dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); 1169 EXPECT_EQ(2u, dex_files.size()); 1170 } 1171 1172 TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) { 1173 std::string dex_location = GetScratchDir() + "/RuntimeCompilerFilterOptionUsed.jar"; 1174 Copy(GetDexSrc1(), dex_location); 1175 1176 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 1177 1178 std::string error_msg; 1179 Runtime::Current()->AddCompilerOption("--compiler-filter=quicken"); 1180 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 1181 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) << 1182 error_msg; 1183 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 1184 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 1185 EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, 1186 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 1187 1188 Runtime::Current()->AddCompilerOption("--compiler-filter=speed"); 1189 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 1190 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) 1191 << error_msg; 1192 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 1193 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); 1194 EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, 1195 oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 1196 1197 Runtime::Current()->AddCompilerOption("--compiler-filter=bogus"); 1198 EXPECT_EQ(OatFileAssistant::kUpdateNotAttempted, 1199 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)); 1200 } 1201 1202 TEST(OatFileAssistantUtilsTest, DexLocationToOdexFilename) { 1203 std::string error_msg; 1204 std::string odex_file; 1205 1206 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename( 1207 "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg; 1208 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file); 1209 1210 EXPECT_TRUE(OatFileAssistant::DexLocationToOdexFilename( 1211 "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg; 1212 EXPECT_EQ("/foo/bar/oat/arm/baz.odex", odex_file); 1213 1214 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename( 1215 "nopath.jar", kArm, &odex_file, &error_msg)); 1216 EXPECT_FALSE(OatFileAssistant::DexLocationToOdexFilename( 1217 "/foo/bar/baz_noext", kArm, &odex_file, &error_msg)); 1218 } 1219 1220 // Verify the dexopt status values from dalvik.system.DexFile 1221 // match the OatFileAssistant::DexOptStatus values. 1222 TEST_F(OatFileAssistantTest, DexOptStatusValues) { 1223 std::pair<OatFileAssistant::DexOptNeeded, const char*> mapping[] = { 1224 {OatFileAssistant::kNoDexOptNeeded, "NO_DEXOPT_NEEDED"}, 1225 {OatFileAssistant::kDex2OatFromScratch, "DEX2OAT_FROM_SCRATCH"}, 1226 {OatFileAssistant::kDex2OatForBootImage, "DEX2OAT_FOR_BOOT_IMAGE"}, 1227 {OatFileAssistant::kDex2OatForFilter, "DEX2OAT_FOR_FILTER"}, 1228 {OatFileAssistant::kDex2OatForRelocation, "DEX2OAT_FOR_RELOCATION"}, 1229 }; 1230 1231 ScopedObjectAccess soa(Thread::Current()); 1232 StackHandleScope<1> hs(soa.Self()); 1233 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 1234 Handle<mirror::Class> dexfile( 1235 hs.NewHandle(linker->FindSystemClass(soa.Self(), "Ldalvik/system/DexFile;"))); 1236 ASSERT_FALSE(dexfile == nullptr); 1237 linker->EnsureInitialized(soa.Self(), dexfile, true, true); 1238 1239 for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) { 1240 ArtField* art_field = mirror::Class::FindStaticField( 1241 soa.Self(), dexfile.Get(), field.second, "I"); 1242 ASSERT_FALSE(art_field == nullptr); 1243 EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt); 1244 EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get())); 1245 } 1246 } 1247 1248 // Verify that when no compiler filter is passed the default one from OatFileAssistant is used. 1249 TEST_F(OatFileAssistantTest, DefaultMakeUpToDateFilter) { 1250 std::string dex_location = GetScratchDir() + "/TestDex.jar"; 1251 Copy(GetDexSrc1(), dex_location); 1252 1253 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 1254 1255 const CompilerFilter::Filter default_filter = 1256 OatFileAssistant::kDefaultCompilerFilterForDexLoading; 1257 std::string error_msg; 1258 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, 1259 oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg)) << 1260 error_msg; 1261 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 1262 oat_file_assistant.GetDexOptNeeded(default_filter)); 1263 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1264 EXPECT_NE(nullptr, oat_file.get()); 1265 EXPECT_EQ(default_filter, oat_file->GetCompilerFilter()); 1266 } 1267 1268 TEST_F(OatFileAssistantTest, MakeUpToDateWithSpecialSharedLibrary) { 1269 std::string dex_location = GetScratchDir() + "/TestDex.jar"; 1270 Copy(GetDexSrc1(), dex_location); 1271 1272 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 1273 1274 const CompilerFilter::Filter default_filter = 1275 OatFileAssistant::kDefaultCompilerFilterForDexLoading; 1276 std::string error_msg; 1277 int status = oat_file_assistant.MakeUpToDate(false, kSpecialSharedLibraryContext, &error_msg); 1278 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg; 1279 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 1280 oat_file_assistant.GetDexOptNeeded(default_filter)); 1281 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1282 EXPECT_NE(nullptr, oat_file.get()); 1283 EXPECT_EQ(kSpecialSharedLibrary, 1284 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey)); 1285 } 1286 1287 TEST_F(OatFileAssistantTest, MakeUpToDateWithContext) { 1288 std::string dex_location = GetScratchDir() + "/TestDex.jar"; 1289 std::string context_location = GetScratchDir() + "/ContextDex.jar"; 1290 Copy(GetDexSrc1(), dex_location); 1291 Copy(GetDexSrc2(), context_location); 1292 1293 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 1294 1295 const CompilerFilter::Filter default_filter = 1296 OatFileAssistant::kDefaultCompilerFilterForDexLoading; 1297 std::string error_msg; 1298 std::string context_str = "PCL[" + context_location + "]"; 1299 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str); 1300 ASSERT_TRUE(context != nullptr); 1301 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, "")); 1302 1303 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg); 1304 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg; 1305 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 1306 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get())); 1307 1308 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1309 EXPECT_NE(nullptr, oat_file.get()); 1310 EXPECT_EQ(context->EncodeContextForOatFile(""), 1311 oat_file->GetOatHeader().GetStoreValueByKey(OatHeader::kClassPathKey)); 1312 } 1313 1314 TEST_F(OatFileAssistantTest, GetDexOptNeededWithOutOfDateContext) { 1315 std::string dex_location = GetScratchDir() + "/TestDex.jar"; 1316 std::string context_location = GetScratchDir() + "/ContextDex.jar"; 1317 Copy(GetDexSrc1(), dex_location); 1318 Copy(GetDexSrc2(), context_location); 1319 1320 OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); 1321 1322 const CompilerFilter::Filter default_filter = 1323 OatFileAssistant::kDefaultCompilerFilterForDexLoading; 1324 std::string error_msg; 1325 std::string context_str = "PCL[" + context_location + "]"; 1326 std::unique_ptr<ClassLoaderContext> context = ClassLoaderContext::Create(context_str); 1327 ASSERT_TRUE(context != nullptr); 1328 ASSERT_TRUE(context->OpenDexFiles(kRuntimeISA, "")); 1329 1330 int status = oat_file_assistant.MakeUpToDate(false, context.get(), &error_msg); 1331 EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, status) << error_msg; 1332 EXPECT_EQ(-OatFileAssistant::kNoDexOptNeeded, 1333 oat_file_assistant.GetDexOptNeeded(default_filter, false, false, context.get())); 1334 1335 // Update the context by overriding the jar file. 1336 Copy(GetMultiDexSrc2(), context_location); 1337 std::unique_ptr<ClassLoaderContext> updated_context = ClassLoaderContext::Create(context_str); 1338 ASSERT_TRUE(updated_context != nullptr); 1339 // DexOptNeeded should advise compilation from scratch. 1340 EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, 1341 oat_file_assistant.GetDexOptNeeded( 1342 default_filter, false, false, updated_context.get())); 1343 } 1344 1345 // TODO: More Tests: 1346 // * Test class linker falls back to unquickened dex for DexNoOat 1347 // * Test class linker falls back to unquickened dex for MultiDexNoOat 1348 // * Test using secondary isa 1349 // * Test for status of oat while oat is being generated (how?) 1350 // * Test case where 32 and 64 bit boot class paths differ, 1351 // and we ask IsInBootClassPath for a class in exactly one of the 32 or 1352 // 64 bit boot class paths. 1353 // * Test unexpected scenarios (?): 1354 // - Dex is stripped, don't have odex. 1355 // - Oat file corrupted after status check, before reload unexecutable 1356 // because it's unrelocated and no dex2oat 1357 } // namespace art 1358