• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
35 namespace art {
36 
37 // Test class that provides some helpers to set a test up for compilation using dex2oat.
38 class Dex2oatEnvironmentTest : public CommonRuntimeTest {
39  public:
SetUp()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 
SetUpRuntimeOptions(RuntimeOptions * options)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 
TearDown()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 
Copy(const std::string & src,const std::string & dst)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).
GetImageDirectory()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 
GetImageLocation()129   std::string GetImageLocation() const {
130     return GetImageDirectory() + "/core.art";
131   }
132 
GetSystemImageFile()133   std::string GetSystemImageFile() const {
134     return GetImageDirectory() + "/" + GetInstructionSetString(kRuntimeISA)
135       + "/core.art";
136   }
137 
GetCachedImageFile(std::string * image,std::string * error_msg)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 
GetDexSrc1()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.
GetStrippedDexSrc1()149   std::string GetStrippedDexSrc1() const {
150     return GetTestDexFileName("MainStripped");
151   }
152 
GetMultiDexSrc1()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.
GetMultiDexSrc2()159   std::string GetMultiDexSrc2() const {
160     return GetTestDexFileName("MultiDexModifiedSecondary");
161   }
162 
GetDexSrc2()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).
GetScratchDir()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.
GetOdexDir()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