Home | History | Annotate | Download | only in runtime
      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 #ifndef ART_RUNTIME_DEX2OAT_ENVIRONMENT_TEST_H_
     18 #define ART_RUNTIME_DEX2OAT_ENVIRONMENT_TEST_H_
     19 
     20 #include <fstream>
     21 #include <string>
     22 #include <vector>
     23 
     24 #include <gtest/gtest.h>
     25 
     26 #include "base/file_utils.h"
     27 #include "base/os.h"
     28 #include "base/stl_util.h"
     29 #include "base/utils.h"
     30 #include "common_runtime_test.h"
     31 #include "compiler_callbacks.h"
     32 #include "dex/art_dex_file_loader.h"
     33 #include "dex/dex_file_loader.h"
     34 #include "exec_utils.h"
     35 #include "gc/heap.h"
     36 #include "gc/space/image_space.h"
     37 #include "oat_file_assistant.h"
     38 #include "runtime.h"
     39 
     40 namespace art {
     41 
     42 // Test class that provides some helpers to set a test up for compilation using dex2oat.
     43 class Dex2oatEnvironmentTest : public CommonRuntimeTest {
     44  public:
     45   virtual void SetUp() OVERRIDE {
     46     CommonRuntimeTest::SetUp();
     47     const ArtDexFileLoader dex_file_loader;
     48 
     49     // Create a scratch directory to work from.
     50 
     51     // Get the realpath of the android data. The oat dir should always point to real location
     52     // when generating oat files in dalvik-cache. This avoids complicating the unit tests
     53     // when matching the expected paths.
     54     UniqueCPtr<const char[]> android_data_real(realpath(android_data_.c_str(), nullptr));
     55     ASSERT_TRUE(android_data_real != nullptr)
     56       << "Could not get the realpath of the android data" << android_data_ << strerror(errno);
     57 
     58     scratch_dir_.assign(android_data_real.get());
     59     scratch_dir_ += "/Dex2oatEnvironmentTest";
     60     ASSERT_EQ(0, mkdir(scratch_dir_.c_str(), 0700));
     61 
     62     // Create a subdirectory in scratch for odex files.
     63     odex_oat_dir_ = scratch_dir_ + "/oat";
     64     ASSERT_EQ(0, mkdir(odex_oat_dir_.c_str(), 0700));
     65 
     66     odex_dir_ = odex_oat_dir_ + "/" + std::string(GetInstructionSetString(kRuntimeISA));
     67     ASSERT_EQ(0, mkdir(odex_dir_.c_str(), 0700));
     68 
     69     // Verify the environment is as we expect
     70     std::vector<uint32_t> checksums;
     71     std::string error_msg;
     72     ASSERT_TRUE(OS::FileExists(GetSystemImageFile().c_str()))
     73       << "Expected pre-compiled boot image to be at: " << GetSystemImageFile();
     74     ASSERT_TRUE(OS::FileExists(GetDexSrc1().c_str()))
     75       << "Expected dex file to be at: " << GetDexSrc1();
     76     ASSERT_TRUE(OS::FileExists(GetStrippedDexSrc1().c_str()))
     77       << "Expected stripped dex file to be at: " << GetStrippedDexSrc1();
     78     ASSERT_FALSE(
     79         dex_file_loader.GetMultiDexChecksums(GetStrippedDexSrc1().c_str(), &checksums, &error_msg))
     80       << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1();
     81     ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
     82       << "Expected dex file to be at: " << GetDexSrc2();
     83 
     84     // GetMultiDexSrc2 should have the same primary dex checksum as
     85     // GetMultiDexSrc1, but a different secondary dex checksum.
     86     static constexpr bool kVerifyChecksum = true;
     87     std::vector<std::unique_ptr<const DexFile>> multi1;
     88     ASSERT_TRUE(dex_file_loader.Open(GetMultiDexSrc1().c_str(),
     89                                      GetMultiDexSrc1().c_str(),
     90                                      /* verify */ true,
     91                                      kVerifyChecksum,
     92                                      &error_msg,
     93                                      &multi1)) << error_msg;
     94     ASSERT_GT(multi1.size(), 1u);
     95 
     96     std::vector<std::unique_ptr<const DexFile>> multi2;
     97     ASSERT_TRUE(dex_file_loader.Open(GetMultiDexSrc2().c_str(),
     98                                      GetMultiDexSrc2().c_str(),
     99                                      /* verify */ true,
    100                                      kVerifyChecksum,
    101                                      &error_msg,
    102                                      &multi2)) << error_msg;
    103     ASSERT_GT(multi2.size(), 1u);
    104 
    105     ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum());
    106     ASSERT_NE(multi1[1]->GetLocationChecksum(), multi2[1]->GetLocationChecksum());
    107   }
    108 
    109   virtual void SetUpRuntimeOptions(RuntimeOptions* options) OVERRIDE {
    110     // options->push_back(std::make_pair("-verbose:oat", nullptr));
    111 
    112     // Set up the image location.
    113     options->push_back(std::make_pair("-Ximage:" + GetImageLocation(),
    114           nullptr));
    115     // Make sure compilercallbacks are not set so that relocation will be
    116     // enabled.
    117     callbacks_.reset();
    118   }
    119 
    120   virtual void TearDown() OVERRIDE {
    121     ClearDirectory(odex_dir_.c_str());
    122     ASSERT_EQ(0, rmdir(odex_dir_.c_str()));
    123 
    124     ClearDirectory(odex_oat_dir_.c_str());
    125     ASSERT_EQ(0, rmdir(odex_oat_dir_.c_str()));
    126 
    127     ClearDirectory(scratch_dir_.c_str());
    128     ASSERT_EQ(0, rmdir(scratch_dir_.c_str()));
    129 
    130     CommonRuntimeTest::TearDown();
    131   }
    132 
    133   static void Copy(const std::string& src, const std::string& dst) {
    134     std::ifstream  src_stream(src, std::ios::binary);
    135     std::ofstream  dst_stream(dst, std::ios::binary);
    136 
    137     dst_stream << src_stream.rdbuf();
    138   }
    139 
    140   // Returns the directory where the pre-compiled core.art can be found.
    141   // TODO: We should factor out this into common tests somewhere rather than
    142   // re-hardcoding it here (This was copied originally from the elf writer
    143   // test).
    144   std::string GetImageDirectory() const {
    145     if (IsHost()) {
    146       const char* host_dir = getenv("ANDROID_HOST_OUT");
    147       CHECK(host_dir != nullptr);
    148       return std::string(host_dir) + "/framework";
    149     } else {
    150       return std::string("/data/art-test");
    151     }
    152   }
    153 
    154   std::string GetImageLocation() const {
    155     return GetImageDirectory() + "/core.art";
    156   }
    157 
    158   std::string GetSystemImageFile() const {
    159     return GetImageDirectory() + "/" + GetInstructionSetString(kRuntimeISA)
    160       + "/core.art";
    161   }
    162 
    163   // Returns the path to an image location whose contents differ from the
    164   // image at GetImageLocation(). This is used for testing mismatched
    165   // image checksums in the oat_file_assistant_tests.
    166   std::string GetImageLocation2() const {
    167     return GetImageDirectory() + "/core-interpreter.art";
    168   }
    169 
    170   std::string GetDexSrc1() const {
    171     return GetTestDexFileName("Main");
    172   }
    173 
    174   // Returns the path to a dex file equivalent to GetDexSrc1, but with the dex
    175   // file stripped.
    176   std::string GetStrippedDexSrc1() const {
    177     return GetTestDexFileName("MainStripped");
    178   }
    179 
    180   std::string GetMultiDexSrc1() const {
    181     return GetTestDexFileName("MultiDex");
    182   }
    183 
    184   // Returns the path to a multidex file equivalent to GetMultiDexSrc2, but
    185   // with the contents of the secondary dex file changed.
    186   std::string GetMultiDexSrc2() const {
    187     return GetTestDexFileName("MultiDexModifiedSecondary");
    188   }
    189 
    190   std::string GetDexSrc2() const {
    191     return GetTestDexFileName("Nested");
    192   }
    193 
    194   // Scratch directory, for dex and odex files (oat files will go in the
    195   // dalvik cache).
    196   const std::string& GetScratchDir() const {
    197     return scratch_dir_;
    198   }
    199 
    200   // Odex directory is the subdirectory in the scratch directory where odex
    201   // files should be located.
    202   const std::string& GetOdexDir() const {
    203     return odex_dir_;
    204   }
    205 
    206  private:
    207   std::string scratch_dir_;
    208   std::string odex_oat_dir_;
    209   std::string odex_dir_;
    210 };
    211 
    212 }  // namespace art
    213 
    214 #endif  // ART_RUNTIME_DEX2OAT_ENVIRONMENT_TEST_H_
    215