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