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