oat_file_assistant_test.cc revision 66d874d96d5699bb090c59f47a5a528956ca053e
166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler/*
266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * Copyright (C) 2014 The Android Open Source Project
366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler *
466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * Licensed under the Apache License, Version 2.0 (the "License");
566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * you may not use this file except in compliance with the License.
666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * You may obtain a copy of the License at
766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler *
866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler *      http://www.apache.org/licenses/LICENSE-2.0
966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler *
1066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * Unless required by applicable law or agreed to in writing, software
1166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * distributed under the License is distributed on an "AS IS" BASIS,
1266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * See the License for the specific language governing permissions and
1466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler * limitations under the License.
1566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler */
1666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
1766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "oat_file_assistant.h"
1866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
1966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include <algorithm>
2066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include <fstream>
2166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include <string>
2266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include <vector>
2366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include <sys/param.h>
2466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
2566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include <backtrace/BacktraceMap.h>
2666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include <gtest/gtest.h>
2766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
2866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "class_linker.h"
2966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "common_runtime_test.h"
3066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "mem_map.h"
3166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "os.h"
3266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "thread-inl.h"
3366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler#include "utils.h"
3466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
3566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhlernamespace art {
3666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
3766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhlerclass OatFileAssistantTest : public CommonRuntimeTest {
3866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler public:
3966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  virtual void SetUp() {
4066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ReserveImageSpace();
4166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    CommonRuntimeTest::SetUp();
4266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
4366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // Create a scratch directory to work from.
4466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    scratch_dir_ = android_data_ + "/OatFileAssistantTest";
4566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_EQ(0, mkdir(scratch_dir_.c_str(), 0700));
4666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
4766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // Create a subdirectory in scratch for the current isa.
4866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // This is the location that will be used for odex files in the tests.
4966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    isa_dir_ = scratch_dir_ + "/" + GetInstructionSetString(kRuntimeISA);
5066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_EQ(0, mkdir(isa_dir_.c_str(), 0700));
5166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
5266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // Verify the environment is as we expect
5366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    uint32_t checksum;
5466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::string error_msg;
5566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_TRUE(OS::FileExists(GetImageFile().c_str()))
5666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      << "Expected pre-compiled boot image to be at: " << GetImageFile();
5766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_TRUE(OS::FileExists(GetDexSrc1().c_str()))
5866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      << "Expected dex file to be at: " << GetDexSrc1();
5966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_TRUE(OS::FileExists(GetStrippedDexSrc1().c_str()))
6066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      << "Expected stripped dex file to be at: " << GetStrippedDexSrc1();
6166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_FALSE(DexFile::GetChecksum(GetStrippedDexSrc1().c_str(), &checksum, &error_msg))
6266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1();
6366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_TRUE(OS::FileExists(GetMultiDexSrc1().c_str()))
6466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      << "Expected multidex file to be at: " << GetMultiDexSrc1();
6566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
6666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      << "Expected dex file to be at: " << GetDexSrc2();
6766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
6866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
6966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
7066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // options->push_back(std::make_pair("-verbose:oat", nullptr));
7166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
7266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // Set up the image location.
7366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    options->push_back(std::make_pair("-Ximage:" + GetImageLocation(),
7466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler          nullptr));
7566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // Make sure compilercallbacks are not set so that relocation will be
7666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // enabled.
7766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    for (std::pair<std::string, const void*>& pair : *options) {
7866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      if (pair.first == "compilercallbacks") {
7966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        pair.second = nullptr;
8066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      }
8166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    }
8266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
8366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
8466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  virtual void PreRuntimeCreate() {
8566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    UnreserveImageSpace();
8666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
8766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
8866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  virtual void PostRuntimeCreate() {
8966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ReserveImageSpace();
9066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
9166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
9266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  virtual void TearDown() {
9366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ClearDirectory(isa_dir_.c_str());
9466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_EQ(0, rmdir(isa_dir_.c_str()));
9566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
9666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ClearDirectory(scratch_dir_.c_str());
9766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_EQ(0, rmdir(scratch_dir_.c_str()));
9866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
9966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    CommonRuntimeTest::TearDown();
10066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
10166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
10266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  void Copy(std::string src, std::string dst) {
10366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::ifstream  src_stream(src, std::ios::binary);
10466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::ofstream  dst_stream(dst, std::ios::binary);
10566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
10666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    dst_stream << src_stream.rdbuf();
10766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
10866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
10966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Returns the directory where the pre-compiled core.art can be found.
11066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // TODO: We should factor out this into common tests somewhere rather than
11166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // re-hardcoding it here (This was copied originally from the elf writer
11266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // test).
11366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetImageDirectory() {
11466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    if (IsHost()) {
11566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      const char* host_dir = getenv("ANDROID_HOST_OUT");
11666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      CHECK(host_dir != NULL);
11766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      return std::string(host_dir) + "/framework";
11866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    } else {
11966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      return std::string("/data/art-test");
12066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    }
12166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
12266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
12366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetImageLocation() {
12466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return GetImageDirectory() + "/core.art";
12566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
12666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
12766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetImageFile() {
12866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return GetImageDirectory() + "/" + GetInstructionSetString(kRuntimeISA)
12966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      + "/core.art";
13066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
13166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
13266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetDexSrc1() {
13366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return GetTestDexFileName("Main");
13466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
13566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
13666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Returns the path to a dex file equivalent to GetDexSrc1, but with the dex
13766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // file stripped.
13866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetStrippedDexSrc1() {
13966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return GetTestDexFileName("MainStripped");
14066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
14166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
14266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetMultiDexSrc1() {
14366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return GetTestDexFileName("MultiDex");
14466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
14566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
14666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetDexSrc2() {
14766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return GetTestDexFileName("Nested");
14866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
14966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
15066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Scratch directory, for dex and odex files (oat files will go in the
15166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // dalvik cache).
15266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetScratchDir() {
15366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return scratch_dir_;
15466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
15566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
15666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // ISA directory is the subdirectory in the scratch directory where odex
15766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // files should be located.
15866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string GetISADir() {
15966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return isa_dir_;
16066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
16166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
16266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Generate an odex file for the purposes of test.
16366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // If pic is true, generates a PIC odex.
16466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  void GenerateOdexForTest(const std::string& dex_location,
16566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler                           const std::string& odex_location,
16666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler                           bool pic = false) {
16766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // For this operation, we temporarily redirect the dalvik cache so dex2oat
16866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // doesn't find the relocated image file.
16966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::string android_data_tmp = GetScratchDir() + "AndroidDataTmp";
17066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    setenv("ANDROID_DATA", android_data_tmp.c_str(), 1);
17166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::vector<std::string> args;
17266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    args.push_back("--dex-file=" + dex_location);
17366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    args.push_back("--oat-file=" + odex_location);
17466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    if (pic) {
17566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      args.push_back("--compile-pic");
17666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    } else {
17766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      args.push_back("--include-patch-information");
17866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    }
17966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    args.push_back("--runtime-arg");
18066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    args.push_back("-Xnorelocate");
18166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::string error_msg;
18266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
18366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    setenv("ANDROID_DATA", android_data_.c_str(), 1);
18466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
18566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
18666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  void GeneratePicOdexForTest(const std::string& dex_location,
18766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler                              const std::string& odex_location) {
18866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    GenerateOdexForTest(dex_location, odex_location, true);
18966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
19066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
19166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler private:
19266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Reserve memory around where the image will be loaded so other memory
19366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // won't conflict when it comes time to load the image.
19466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // This can be called with an already loaded image to reserve the space
19566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // around it.
19666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  void ReserveImageSpace() {
19766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    MemMap::Init();
19866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
19966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // Ensure a chunk of memory is reserved for the image space.
20066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    uintptr_t reservation_start = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MIN_DELTA;
20166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    uintptr_t reservation_end = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MAX_DELTA
20266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      + 100 * 1024 * 1024;
20366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
20466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::string error_msg;
20566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true));
20666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ASSERT_TRUE(map.get() != nullptr) << "Failed to build process map";
20766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    for (BacktraceMap::const_iterator it = map->begin();
20866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        reservation_start < reservation_end && it != map->end(); ++it) {
20966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      if (it->end <= reservation_start) {
21066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        continue;
21166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      }
21266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
21366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      if (it->start < reservation_start) {
21466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        reservation_start = std::min(reservation_end, it->end);
21566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      }
21666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
21766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      image_reservation_.push_back(std::unique_ptr<MemMap>(
21866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler          MemMap::MapAnonymous("image reservation",
21966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler              reinterpret_cast<uint8_t*>(reservation_start),
22066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler              std::min(it->start, reservation_end) - reservation_start,
22166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler              PROT_NONE, false, false, &error_msg)));
22266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      ASSERT_TRUE(image_reservation_.back().get() != nullptr) << error_msg;
22366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      LOG(INFO) << "Reserved space for image " <<
22466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        reinterpret_cast<void*>(image_reservation_.back()->Begin()) << "-" <<
22566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        reinterpret_cast<void*>(image_reservation_.back()->End());
22666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      reservation_start = it->end;
22766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    }
22866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
22966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
23066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
23166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Unreserve any memory reserved by ReserveImageSpace. This should be called
23266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // before the image is loaded.
23366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  void UnreserveImageSpace() {
23466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    image_reservation_.clear();
23566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
23666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
23766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string scratch_dir_;
23866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string isa_dir_;
23966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<MemMap>> image_reservation_;
24066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler};
24166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
24266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhlerclass OatFileAssistantNoDex2OatTest : public OatFileAssistantTest {
24366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler public:
24466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
24566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    OatFileAssistantTest::SetUpRuntimeOptions(options);
24666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    options->push_back(std::make_pair("-Xnodex2oat", nullptr));
24766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
24866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler};
24966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
25066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Generate an oat file for the purposes of test, as opposed to testing
25166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// generation of oat files.
25266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhlerstatic void GenerateOatForTest(const char* dex_location) {
25366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location, kRuntimeISA, false);
25466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
25566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string error_msg;
25666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file_assistant.GenerateOatFile(&error_msg)) << error_msg;
25766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
25866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
25966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file, but no OAT file for it.
26066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kOutOfDate.
26166d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, DexNoOat) {
26266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/DexNoOat.jar";
26366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
26466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
26566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
26666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
26766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
26866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
26966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
27066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
27166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
27266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileNeedsRelocation());
27366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
27466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.OdexFileStatus());
27566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileExists());
27666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
27766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
27866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
27966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.OatFileStatus());
28066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
28166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
28266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have no DEX file and no OAT file.
28366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: Status is out of date. Loading should fail, but not crash.
28466d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, NoDexNoOat) {
28566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/NoDexNoOat.jar";
28666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
28766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
28866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
28966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
29066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
29166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(nullptr, oat_file.get());
29266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
29366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
29466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file and up-to-date OAT file for it.
29566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kUpToDate.
29666d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, OatUpToDate) {
29766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/OatUpToDate.jar";
29866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
29966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOatForTest(dex_location.c_str());
30066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
30166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
30266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
30366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.GetStatus());
30466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
30566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
30666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
30766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
30866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileExists());
30966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
31066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
31166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
31266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.OatFileStatus());
31366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
31466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
31566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a MultiDEX file and up-to-date OAT file for it.
31666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kUpToDate.
31766d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, MultiDexOatUpToDate) {
31866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/MultiDexOatUpToDate.jar";
31966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetMultiDexSrc1(), dex_location);
32066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOatForTest(dex_location.c_str());
32166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
32266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify we can load both dex files.
32366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant executable_oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
32466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = executable_oat_file_assistant.GetBestOatFile();
32566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
32666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file->IsExecutable());
32766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
32866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = executable_oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
32966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(2u, dex_files.size());
33066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
33166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
33266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file and out of date OAT file.
33366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kOutOfDate.
33466d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, OatOutOfDate) {
33566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/OatOutOfDate.jar";
33666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
33766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // We create a dex, generate an oat for it, then overwrite the dex with a
33866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // different dex to make the oat out of date.
33966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
34066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOatForTest(dex_location.c_str());
34166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc2(), dex_location);
34266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
34366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
34466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
34566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
34666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
34766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
34866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
34966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
35066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileExists());
35166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
35266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
35366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
35466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
35566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file and an ODEX file, but no OAT file.
35666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kNeedsRelocation.
35766d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, DexOdexNoOat) {
35866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/DexOdexNoOat.jar";
35966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string odex_location = GetISADir() + "/DexOdexNoOat.odex";
36066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
36166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the dex and odex files
36266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
36366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOdexForTest(dex_location, odex_location);
36466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
36566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify the status.
36666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
36766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
36866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.GetStatus());
36966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
37066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
37166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
37266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
37366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
37466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
37566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.OdexFileNeedsRelocation());
37666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileExists());
37766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
37866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
37966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
38066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
38166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a stripped DEX file and an ODEX file, but no OAT file.
38266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kNeedsRelocation.
38366d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, StrippedDexOdexNoOat) {
38466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/StrippedDexOdexNoOat.jar";
38566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string odex_location = GetISADir() + "/StrippedDexOdexNoOat.odex";
38666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
38766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the dex and odex files
38866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
38966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOdexForTest(dex_location, odex_location);
39066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
39166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Strip the dex file
39266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetStrippedDexSrc1(), dex_location);
39366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
39466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify the status.
39566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
39666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
39766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.GetStatus());
39866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
39966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
40066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
40166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
40266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
40366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileExists());
40466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
40566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
40666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
40766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Make the oat file up to date.
40866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string error_msg;
40966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
41066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
41166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.GetStatus());
41266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
41366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
41466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
41566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
41666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
41766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileExists());
41866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
41966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
42066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
42166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify we can load the dex files from it.
42266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
42366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
42466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file->IsExecutable());
42566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
42666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
42766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(1u, dex_files.size());
42866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
42966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
43066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a stripped DEX file, an ODEX file, and an out of date OAT file.
43166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kNeedsRelocation.
43266d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, StrippedDexOdexOat) {
43366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/StrippedDexOdexOat.jar";
43466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string odex_location = GetISADir() + "/StrippedDexOdexOat.odex";
43566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
43666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the oat file from a different dex file so it looks out of date.
43766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc2(), dex_location);
43866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOatForTest(dex_location.c_str());
43966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
44066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the odex file
44166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
44266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOdexForTest(dex_location, odex_location);
44366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
44466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Strip the dex file.
44566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetStrippedDexSrc1(), dex_location);
44666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
44766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify the status.
44866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
44966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
45066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.GetStatus());
45166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
45266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
45366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
45466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
45566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
45666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
45766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileExists());
45866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
45966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
46066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
46166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Make the oat file up to date.
46266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string error_msg;
46366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
46466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
46566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.GetStatus());
46666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
46766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
46866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
46966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
47066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileNeedsRelocation());
47166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
47266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileExists());
47366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
47466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileNeedsRelocation());
47566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsUpToDate());
47666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
47766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify we can load the dex files from it.
47866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
47966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
48066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file->IsExecutable());
48166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
48266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
48366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(1u, dex_files.size());
48466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
48566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
48666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and
48766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// OAT files both have patch delta of 0.
48866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: It shouldn't crash.
48966d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, OdexOatOverlap) {
49066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/OdexOatOverlap.jar";
49166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string odex_location = GetISADir() + "/OdexOatOverlap.odex";
49266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string oat_location = GetISADir() + "/OdexOatOverlap.oat";
49366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
49466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the dex and odex files
49566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
49666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOdexForTest(dex_location, odex_location);
49766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
49866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the oat file by copying the odex so they are located in the same
49966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // place in memory.
50066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(odex_location, oat_location);
50166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
50266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify things don't go bad.
50366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(),
50466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      oat_location.c_str(), kRuntimeISA, true);
50566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
50666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kNeedsRelocation, oat_file_assistant.GetStatus());
50766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
50866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
50966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
51066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
51166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
51266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileExists());
51366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsOutOfDate());
51466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
51566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
51666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Things aren't relocated, so it should fall back to interpreted.
51766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
51866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
51966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file->IsExecutable());
52066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
52166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
52266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(1u, dex_files.size());
52366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
52466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
52566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file and a PIC ODEX file, but no OAT file.
52666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kUpToDate, because PIC needs no relocation.
52766d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, DexPicOdexNoOat) {
52866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/DexPicOdexNoOat.jar";
52966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string odex_location = GetISADir() + "/DexPicOdexNoOat.odex";
53066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
53166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the dex and odex files
53266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
53366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GeneratePicOdexForTest(dex_location, odex_location);
53466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
53566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify the status.
53666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
53766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
53866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kUpToDate, oat_file_assistant.GetStatus());
53966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
54066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
54166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileExists());
54266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsOutOfDate());
54366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileIsUpToDate());
54466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileExists());
54566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
54666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
54766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
54866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
54966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file and up-to-date OAT file for it.
55066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: We should load an executable dex file.
55166d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, LoadOatUpToDate) {
55266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/LoadOatUpToDate.jar";
55366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
55466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
55566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOatForTest(dex_location.c_str());
55666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
55766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Load the oat using an oat file assistant.
55866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
55966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
56066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
56166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
56266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file->IsExecutable());
56366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
56466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
56566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(1u, dex_files.size());
56666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
56766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
56866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file and up-to-date OAT file for it.
56966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: Loading non-executable should load the oat non-executable.
57066d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, LoadNoExecOatUpToDate) {
57166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/LoadNoExecOatUpToDate.jar";
57266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
57366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
57466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOatForTest(dex_location.c_str());
57566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
57666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Load the oat using an oat file assistant.
57766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
57866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
57966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
58066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
58166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file->IsExecutable());
58266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
58366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
58466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(1u, dex_files.size());
58566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
58666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
58766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file.
58866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: We should load an executable dex file from an alternative oat
58966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// location.
59066d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, LoadDexNoAlternateOat) {
59166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/LoadDexNoAlternateOat.jar";
59266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string oat_location = GetScratchDir() + "/LoadDexNoAlternateOat.oat";
59366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
59466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
59566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
59666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(
59766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      dex_location.c_str(), oat_location.c_str(), kRuntimeISA, true);
59866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string error_msg;
59966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file_assistant.MakeUpToDate(&error_msg)) << error_msg;
60066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
60166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
60266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
60366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file->IsExecutable());
60466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
60566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
60666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(1u, dex_files.size());
60766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
60866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(OS::FileExists(oat_location.c_str()));
60966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
61066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify it didn't create an oat in the default location.
61166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant ofm(dex_location.c_str(), kRuntimeISA, false);
61266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(ofm.OatFileExists());
61366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
61466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
61566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: Non-existent Dex location.
61666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The dex code is out of date, and trying to update it fails.
61766d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, NonExsistentDexLocation) {
61866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/BadDexLocation.jar";
61966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
62066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
62166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
62266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
62366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
62466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
62566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileExists());
62666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
62766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
62866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
62966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
63066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
63166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string error_msg;
63266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.MakeUpToDate(&error_msg));
63366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(error_msg.empty());
63466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
63566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
63666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Turn an absolute path into a path relative to the current working
63766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// directory.
63866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhlerstatic std::string MakePathRelative(std::string target) {
63966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  char buf[MAXPATHLEN];
64066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string cwd = getcwd(buf, MAXPATHLEN);
64166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
64266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Split the target and cwd paths into components.
64366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::string> target_path;
64466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::string> cwd_path;
64566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Split(target, '/', &target_path);
64666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Split(cwd, '/', &cwd_path);
64766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
64866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Reverse the path components, so we can use pop_back().
64966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::reverse(target_path.begin(), target_path.end());
65066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::reverse(cwd_path.begin(), cwd_path.end());
65166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
65266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Drop the common prefix of the paths. Because we reversed the path
65366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // components, this becomes the common suffix of target_path and cwd_path.
65466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  while (!target_path.empty() && !cwd_path.empty()
65566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      && target_path.back() == cwd_path.back()) {
65666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    target_path.pop_back();
65766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    cwd_path.pop_back();
65866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
65966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
66066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // For each element of the remaining cwd_path, add '..' to the beginning
66166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // of the target path. Because we reversed the path components, we add to
66266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // the end of target_path.
66366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  for (unsigned int i = 0; i < cwd_path.size(); i++) {
66466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    target_path.push_back("..");
66566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
66666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
66766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Reverse again to get the right path order, and join to get the result.
66866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::reverse(target_path.begin(), target_path.end());
66966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  return Join(target_path, '/');
67066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
67166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
67266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: Non-absolute path to Dex location.
67366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: Not sure, but it shouldn't crash.
67466d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, NonAbsoluteDexLocation) {
67566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string abs_dex_location = GetScratchDir() + "/NonAbsoluteDexLocation.jar";
67666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), abs_dex_location);
67766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
67866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = MakePathRelative(abs_dex_location);
67966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
68066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
68166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
68266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
68366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
68466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileExists());
68566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
68666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
68766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
68866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
68966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
69066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
69166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: Very short, non-existent Dex location.
69266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: Dex code is out of date, and trying to update it fails.
69366d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, ShortDexLocation) {
69466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = "/xx";
69566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
69666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
69766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
69866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
69966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
70066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
70166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileExists());
70266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
70366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
70466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
70566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
70666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
70766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string error_msg;
70866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.MakeUpToDate(&error_msg));
70966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(error_msg.empty());
71066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
71166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
71266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: Non-standard extension for dex file.
71366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: The oat file status is kOutOfDate.
71466d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, LongDexExtension) {
71566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/LongDexExtension.jarx";
71666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
71766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
71866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false);
71966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
72066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(OatFileAssistant::kOutOfDate, oat_file_assistant.GetStatus());
72166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
72266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.IsInBootClassPath());
72366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileExists());
72466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OdexFileIsOutOfDate());
72566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OdexFileIsUpToDate());
72666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileExists());
72766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(oat_file_assistant.OatFileIsOutOfDate());
72866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file_assistant.OatFileIsUpToDate());
72966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
73066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
73166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// A task to generate a dex location. Used by the RaceToGenerate test.
73266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhlerclass RaceGenerateTask : public Task {
73366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler public:
73466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  explicit RaceGenerateTask(const std::string& dex_location, const std::string& oat_location)
73566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    : dex_location_(dex_location), oat_location_(oat_location),
73666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler      loaded_oat_file_(nullptr)
73766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  {}
73866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
73966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  void Run(Thread* self) {
74066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    UNUSED(self);
74166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
74266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // Load the dex files, and save a pointer to the loaded oat file, so that
74366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    // we can verify only one oat file was loaded for the dex location.
74466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    ClassLinker* linker = Runtime::Current()->GetClassLinker();
74566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::vector<std::unique_ptr<const DexFile>> dex_files;
74666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::vector<std::string> error_msgs;
74766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    dex_files = linker->OpenDexFilesFromOat(dex_location_.c_str(), oat_location_.c_str(), &error_msgs);
74866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    CHECK(!dex_files.empty()) << Join(error_msgs, '\n');
74966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    loaded_oat_file_ = dex_files[0]->GetOatFile();
75066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
75166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
75266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  const OatFile* GetLoadedOatFile() const {
75366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    return loaded_oat_file_;
75466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
75566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
75666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler private:
75766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location_;
75866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string oat_location_;
75966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  const OatFile* loaded_oat_file_;
76066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler};
76166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
76266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Test the case where multiple processes race to generate an oat file.
76366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// This simulates multiple processes using multiple threads.
76466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//
76566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// We want only one Oat file to be loaded when there is a race to load, to
76666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// avoid using up the virtual memory address space.
76766d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantTest, RaceToGenerate) {
76866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/RaceToGenerate.jar";
76966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string oat_location = GetISADir() + "/RaceToGenerate.oat";
77066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
77166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // We use the lib core dex file, because it's large, and hopefully should
77266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // take a while to generate.
77366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetLibCoreDexFileName(), dex_location);
77466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
77566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  const int kNumThreads = 32;
77666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Thread* self = Thread::Current();
77766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ThreadPool thread_pool("Oat file assistant test thread pool", kNumThreads);
77866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<RaceGenerateTask>> tasks;
77966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  for (int i = 0; i < kNumThreads; i++) {
78066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    std::unique_ptr<RaceGenerateTask> task(new RaceGenerateTask(dex_location, oat_location));
78166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    thread_pool.AddTask(self, task.get());
78266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    tasks.push_back(std::move(task));
78366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
78466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  thread_pool.StartWorkers(self);
78566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  thread_pool.Wait(self, true, false);
78666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
78766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Verify every task got the same pointer.
78866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  const OatFile* expected = tasks[0]->GetLoadedOatFile();
78966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  for (auto& task : tasks) {
79066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler    EXPECT_EQ(expected, task->GetLoadedOatFile());
79166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  }
79266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
79366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
79466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a DEX file and an ODEX file, no OAT file, and dex2oat is
79566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// disabled.
79666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: We should load the odex file non-executable.
79766d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantNoDex2OatTest, LoadDexOdexNoOat) {
79866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/LoadDexOdexNoOat.jar";
79966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string odex_location = GetISADir() + "/LoadDexOdexNoOat.odex";
80066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
80166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the dex and odex files
80266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetDexSrc1(), dex_location);
80366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOdexForTest(dex_location, odex_location);
80466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
80566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Load the oat using an executable oat file assistant.
80666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
80766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
80866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
80966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
81066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file->IsExecutable());
81166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
81266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
81366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(1u, dex_files.size());
81466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
81566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
81666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Case: We have a MultiDEX file and an ODEX file, no OAT file, and dex2oat is
81766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// disabled.
81866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// Expect: We should load the odex file non-executable.
81966d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST_F(OatFileAssistantNoDex2OatTest, LoadMultiDexOdexNoOat) {
82066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string dex_location = GetScratchDir() + "/LoadMultiDexOdexNoOat.jar";
82166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string odex_location = GetISADir() + "/LoadMultiDexOdexNoOat.odex";
82266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
82366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Create the dex and odex files
82466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  Copy(GetMultiDexSrc1(), dex_location);
82566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  GenerateOdexForTest(dex_location, odex_location);
82666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
82766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  // Load the oat using an executable oat file assistant.
82866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true);
82966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
83066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
83166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  ASSERT_TRUE(oat_file.get() != nullptr);
83266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(oat_file->IsExecutable());
83366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::vector<std::unique_ptr<const DexFile>> dex_files;
83466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str());
83566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ(2u, dex_files.size());
83666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
83766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
83866d874d96d5699bb090c59f47a5a528956ca053eRichard UhlerTEST(OatFileAssistantUtilsTest, DexFilenameToOdexFilename) {
83966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string error_msg;
84066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  std::string odex_file;
84166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
84266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename(
84366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        "/foo/bar/baz.jar", kArm, &odex_file, &error_msg)) << error_msg;
84466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ("/foo/bar/arm/baz.odex", odex_file);
84566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
84666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_TRUE(OatFileAssistant::DexFilenameToOdexFilename(
84766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        "/foo/bar/baz.funnyext", kArm, &odex_file, &error_msg)) << error_msg;
84866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_EQ("/foo/bar/arm/baz.odex", odex_file);
84966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
85066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename(
85166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        "nopath.jar", kArm, &odex_file, &error_msg));
85266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler  EXPECT_FALSE(OatFileAssistant::DexFilenameToOdexFilename(
85366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler        "/foo/bar/baz_noext", kArm, &odex_file, &error_msg));
85466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}
85566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
85666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
85766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler// TODO: More Tests:
85866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//  * Test class linker falls back to unquickened dex for DexNoOat
85966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//  * Test class linker falls back to unquickened dex for MultiDexNoOat
86066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//  * Test multidex files:
86166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//     - Multidex with only classes2.dex out of date should have status
86266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//       kOutOfDate
86366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//  * Test using secondary isa
86466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//  * Test with profiling info?
86566d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//  * Test for status of oat while oat is being generated (how?)
86666d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//  * Test case where 32 and 64 bit boot class paths differ,
86766d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//      and we ask IsInBootClassPath for a class in exactly one of the 32 or
86866d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//      64 bit boot class paths.
86966d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//  * Test unexpected scenarios (?):
87066d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//    - Dex is stripped, don't have odex.
87166d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//    - Oat file corrupted after status check, before reload unexecutable
87266d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler//    because it's unrelocated and no dex2oat
87366d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler
87466d874d96d5699bb090c59f47a5a528956ca053eRichard Uhler}  // namespace art
875