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