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: SetUp()45 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 SetUpRuntimeOptions(RuntimeOptions * options)109 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 TearDown()120 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 Copy(const std::string & src,const std::string & dst)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 GetDexSrc1()140 std::string GetDexSrc1() const { 141 return GetTestDexFileName("Main"); 142 } 143 144 // Returns the path to a dex file equivalent to GetDexSrc1, but with the dex 145 // file stripped. GetStrippedDexSrc1()146 std::string GetStrippedDexSrc1() const { 147 return GetTestDexFileName("MainStripped"); 148 } 149 GetMultiDexSrc1()150 std::string GetMultiDexSrc1() const { 151 return GetTestDexFileName("MultiDex"); 152 } 153 154 // Returns the path to a multidex file equivalent to GetMultiDexSrc2, but 155 // with the contents of the secondary dex file changed. GetMultiDexSrc2()156 std::string GetMultiDexSrc2() const { 157 return GetTestDexFileName("MultiDexModifiedSecondary"); 158 } 159 GetDexSrc2()160 std::string GetDexSrc2() const { 161 return GetTestDexFileName("Nested"); 162 } 163 164 // Scratch directory, for dex and odex files (oat files will go in the 165 // dalvik cache). GetScratchDir()166 const std::string& GetScratchDir() const { 167 return scratch_dir_; 168 } 169 170 // Odex directory is the subdirectory in the scratch directory where odex 171 // files should be located. GetOdexDir()172 const std::string& GetOdexDir() const { 173 return odex_dir_; 174 } 175 176 private: 177 std::string scratch_dir_; 178 std::string odex_oat_dir_; 179 std::string odex_dir_; 180 }; 181 182 } // namespace art 183 184 #endif // ART_RUNTIME_DEX2OAT_ENVIRONMENT_TEST_H_ 185