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