1 /*
2  * Copyright (C) 2018 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_LIBARTBASE_BASE_COMMON_ART_TEST_H_
18 #define ART_LIBARTBASE_BASE_COMMON_ART_TEST_H_
19 
20 #include <gtest/gtest.h>
21 
22 #include <functional>
23 #include <string>
24 
25 #include <sys/wait.h>
26 
27 #include <android-base/logging.h>
28 
29 #include "base/file_utils.h"
30 #include "base/globals.h"
31 #include "base/memory_tool.h"
32 #include "base/mutex.h"
33 #include "base/os.h"
34 #include "base/unix_file/fd_file.h"
35 #include "dex/art_dex_file_loader.h"
36 #include "dex/compact_dex_level.h"
37 #include "dex/compact_dex_file.h"
38 
39 namespace art {
40 
41 using LogSeverity = android::base::LogSeverity;
42 using ScopedLogSeverity = android::base::ScopedLogSeverity;
43 
44 class DexFile;
45 
46 class ScratchDir {
47  public:
48   ScratchDir();
49 
50   ~ScratchDir();
51 
GetPath()52   const std::string& GetPath() const {
53     return path_;
54   }
55 
56  private:
57   std::string path_;
58 
59   DISALLOW_COPY_AND_ASSIGN(ScratchDir);
60 };
61 
62 class ScratchFile {
63  public:
64   ScratchFile();
65 
66   explicit ScratchFile(const std::string& filename);
67 
68   ScratchFile(const ScratchFile& other, const char* suffix);
69 
70   ScratchFile(ScratchFile&& other) noexcept;
71 
72   ScratchFile& operator=(ScratchFile&& other) noexcept;
73 
74   explicit ScratchFile(File* file);
75 
76   ~ScratchFile();
77 
GetFilename()78   const std::string& GetFilename() const {
79     return filename_;
80   }
81 
GetFile()82   File* GetFile() const {
83     return file_.get();
84   }
85 
86   int GetFd() const;
87 
88   void Close();
89   void Unlink();
90 
91  private:
92   std::string filename_;
93   std::unique_ptr<File> file_;
94 };
95 
96 // Close to store a fake dex file and its underlying data.
97 class FakeDex {
98  public:
Create(const std::string & location,uint32_t checksum,uint32_t num_method_ids)99   static std::unique_ptr<FakeDex> Create(
100       const std::string& location,
101       uint32_t checksum,
102       uint32_t num_method_ids) {
103     FakeDex* fake_dex = new FakeDex();
104     fake_dex->dex = CreateFakeDex(location, checksum, num_method_ids, &fake_dex->storage);
105     return std::unique_ptr<FakeDex>(fake_dex);
106   }
107 
CreateFakeDex(const std::string & location,uint32_t checksum,uint32_t num_method_ids,std::vector<uint8_t> * storage)108   static std::unique_ptr<const DexFile> CreateFakeDex(
109       const std::string& location,
110       uint32_t checksum,
111       uint32_t num_method_ids,
112       std::vector<uint8_t>* storage) {
113     storage->resize(kPageSize);
114     CompactDexFile::Header* header =
115         const_cast<CompactDexFile::Header*>(CompactDexFile::Header::At(storage->data()));
116     CompactDexFile::WriteMagic(header->magic_);
117     CompactDexFile::WriteCurrentVersion(header->magic_);
118     header->data_off_ = 0;
119     header->data_size_ = storage->size();
120     header->method_ids_size_ = num_method_ids;
121 
122     const DexFileLoader dex_file_loader;
123     std::string error_msg;
124     std::unique_ptr<const DexFile> dex(dex_file_loader.Open(storage->data(),
125                                                             storage->size(),
126                                                             location,
127                                                             checksum,
128                                                             /*oat_dex_file=*/nullptr,
129                                                             /*verify=*/false,
130                                                             /*verify_checksum=*/false,
131                                                             &error_msg));
132     CHECK(dex != nullptr) << error_msg;
133     return dex;
134   }
135 
Dex()136   std::unique_ptr<const DexFile>& Dex() {
137     return dex;
138   }
139 
140  private:
141   std::vector<uint8_t> storage;
142   std::unique_ptr<const DexFile> dex;
143 };
144 
145 // Convenience class to store multiple fake dex files in order to make
146 // allocation/de-allocation easier in tests.
147 class FakeDexStorage {
148  public:
AddFakeDex(const std::string & location,uint32_t checksum,uint32_t num_method_ids)149   const DexFile* AddFakeDex(
150       const std::string& location,
151       uint32_t checksum,
152       uint32_t num_method_ids) {
153     fake_dex_files.push_back(FakeDex::Create(location, checksum, num_method_ids));
154     return fake_dex_files.back()->Dex().get();
155   }
156 
157  private:
158   std::vector<std::unique_ptr<FakeDex>> fake_dex_files;
159 };
160 
161 class CommonArtTestImpl {
162  public:
163   CommonArtTestImpl() = default;
164   virtual ~CommonArtTestImpl() = default;
165 
166   // Set up ANDROID_BUILD_TOP, ANDROID_HOST_OUT, ANDROID_ROOT, ANDROID_I18N_ROOT,
167   // ANDROID_ART_ROOT, and ANDROID_TZDATA_ROOT environment variables using sensible defaults
168   // if not already set.
169   static void SetUpAndroidRootEnvVars();
170 
171   // Set up the ANDROID_DATA environment variable, creating the directory if required.
172   // Note: setting up ANDROID_DATA may create a temporary directory. If this is used in a
173   // non-derived class, be sure to also call the corresponding tear-down below.
174   static void SetUpAndroidDataDir(std::string& android_data);
175 
176   static void TearDownAndroidDataDir(const std::string& android_data, bool fail_on_error);
177 
178   // Get the names of the libcore modules.
179   virtual std::vector<std::string> GetLibCoreModuleNames() const;
180 
181   // Gets the paths of the libcore dex files for given modules.
182   std::vector<std::string> GetLibCoreDexFileNames(const std::vector<std::string>& modules) const;
183 
184   // Gets the paths of the libcore dex files.
185   std::vector<std::string> GetLibCoreDexFileNames() const;
186 
187   // Gets the locations of the libcore dex files for given modules.
188   std::vector<std::string> GetLibCoreDexLocations(const std::vector<std::string>& modules) const;
189 
190   // Gets the locations of the libcore dex files.
191   std::vector<std::string> GetLibCoreDexLocations() const;
192 
193   static std::string GetClassPathOption(const char* option,
194                                         const std::vector<std::string>& class_path);
195 
196   // Returns bin directory which contains host's prebuild tools.
197   static std::string GetAndroidHostToolsDir();
198 
199   // Retuerns the filename for a test dex (i.e. XandY or ManyMethods).
200   std::string GetTestDexFileName(const char* name) const;
201 
202   template <typename Mutator>
MutateDexFile(File * output_dex,const std::string & input_jar,const Mutator & mutator)203   bool MutateDexFile(File* output_dex, const std::string& input_jar, const Mutator& mutator) {
204     std::vector<std::unique_ptr<const DexFile>> dex_files;
205     std::string error_msg;
206     const ArtDexFileLoader dex_file_loader;
207     CHECK(dex_file_loader.Open(input_jar.c_str(),
208                                input_jar.c_str(),
209                                /*verify*/ true,
210                                /*verify_checksum*/ true,
211                                &error_msg,
212                                &dex_files)) << error_msg;
213     EXPECT_EQ(dex_files.size(), 1u) << "Only one input dex is supported";
214     const std::unique_ptr<const DexFile>& dex = dex_files[0];
215     CHECK(dex->EnableWrite()) << "Failed to enable write";
216     DexFile* dex_file = const_cast<DexFile*>(dex.get());
217     mutator(dex_file);
218     const_cast<DexFile::Header&>(dex_file->GetHeader()).checksum_ = dex_file->CalculateChecksum();
219     if (!output_dex->WriteFully(dex->Begin(), dex->Size())) {
220       return false;
221     }
222     if (output_dex->Flush() != 0) {
223       PLOG(FATAL) << "Could not flush the output file.";
224     }
225     return true;
226   }
227 
228   struct ForkAndExecResult {
229     enum Stage {
230       kLink,
231       kFork,
232       kWaitpid,
233       kFinished,
234     };
235     Stage stage;
236     int status_code;
237 
StandardSuccessForkAndExecResult238     bool StandardSuccess() {
239       return stage == kFinished && WIFEXITED(status_code) && WEXITSTATUS(status_code) == 0;
240     }
241   };
242   using OutputHandlerFn = std::function<void(char*, size_t)>;
243   using PostForkFn = std::function<bool()>;
244   static ForkAndExecResult ForkAndExec(const std::vector<std::string>& argv,
245                                        const PostForkFn& post_fork,
246                                        const OutputHandlerFn& handler);
247   static ForkAndExecResult ForkAndExec(const std::vector<std::string>& argv,
248                                        const PostForkFn& post_fork,
249                                        std::string* output);
250 
251  protected:
IsHost()252   static bool IsHost() {
253     return !kIsTargetBuild;
254   }
255 
256   // Helper - find directory with the following format:
257   // ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
258   static std::string GetAndroidToolsDir(const std::string& subdir1,
259                                         const std::string& subdir2,
260                                         const std::string& subdir3);
261 
262   // File location to core.art, e.g. $ANDROID_HOST_OUT/system/framework/core.art
263   static std::string GetCoreArtLocation();
264 
265   // File location to core.oat, e.g. $ANDROID_HOST_OUT/system/framework/core.oat
266   static std::string GetCoreOatLocation();
267 
268   std::unique_ptr<const DexFile> LoadExpectSingleDexFile(const char* location);
269 
270   void ClearDirectory(const char* dirpath, bool recursive = true);
271 
272   // Open a file (allows reading of framework jars).
273   std::vector<std::unique_ptr<const DexFile>> OpenDexFiles(const char* filename);
274 
275   // Open a single dex file (aborts if there are more than one).
276   std::unique_ptr<const DexFile> OpenDexFile(const char* filename);
277 
278   // Open a test file (art-gtest-*.jar).
279   std::vector<std::unique_ptr<const DexFile>> OpenTestDexFiles(const char* name);
280 
281   std::unique_ptr<const DexFile> OpenTestDexFile(const char* name);
282 
283 
284   std::string android_data_;
285   std::string dalvik_cache_;
286 
287   virtual void SetUp();
288 
289   virtual void TearDown();
290 
291   // Creates the class path string for the given dex files (the list of dex file locations
292   // separated by ':').
293   std::string CreateClassPath(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
294   // Same as CreateClassPath but add the dex file checksum after each location. The separator
295   // is '*'.
296   std::string CreateClassPathWithChecksums(
297       const std::vector<std::unique_ptr<const DexFile>>& dex_files);
298 
299   static std::string GetCoreFileLocation(const char* suffix);
300 
301   std::vector<std::unique_ptr<const DexFile>> loaded_dex_files_;
302 };
303 
304 template <typename TestType>
305 class CommonArtTestBase : public TestType, public CommonArtTestImpl {
306  public:
CommonArtTestBase()307   CommonArtTestBase() {}
~CommonArtTestBase()308   virtual ~CommonArtTestBase() {}
309 
310  protected:
SetUp()311   void SetUp() override {
312     CommonArtTestImpl::SetUp();
313   }
314 
TearDown()315   void TearDown() override {
316     CommonArtTestImpl::TearDown();
317   }
318 };
319 
320 using CommonArtTest = CommonArtTestBase<testing::Test>;
321 
322 template <typename Param>
323 using CommonArtTestWithParam = CommonArtTestBase<testing::TestWithParam<Param>>;
324 
325 #define TEST_DISABLED_FOR_TARGET() \
326   if (kIsTargetBuild) { \
327     printf("WARNING: TEST DISABLED FOR TARGET\n"); \
328     return; \
329   }
330 
331 #define TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS() \
332   if (!kHostStaticBuildEnabled) { \
333     printf("WARNING: TEST DISABLED FOR NON-STATIC HOST BUILDS\n"); \
334     return; \
335   }
336 
337 #define TEST_DISABLED_FOR_MEMORY_TOOL() \
338   if (kRunningOnMemoryTool) { \
339     printf("WARNING: TEST DISABLED FOR MEMORY TOOL\n"); \
340     return; \
341   }
342 
343 #define TEST_DISABLED_FOR_HEAP_POISONING() \
344   if (kPoisonHeapReferences) { \
345     printf("WARNING: TEST DISABLED FOR HEAP POISONING\n"); \
346     return; \
347   }
348 }  // namespace art
349 
350 #define TEST_DISABLED_FOR_MEMORY_TOOL_WITH_HEAP_POISONING() \
351   if (kRunningOnMemoryTool && kPoisonHeapReferences) { \
352     printf("WARNING: TEST DISABLED FOR MEMORY TOOL WITH HEAP POISONING\n"); \
353     return; \
354   }
355 
356 #endif  // ART_LIBARTBASE_BASE_COMMON_ART_TEST_H_
357