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