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