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