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