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/globals.h"
30 #include "base/mutex.h"
31 #include "base/os.h"
32 #include "base/unix_file/fd_file.h"
33 #include "dex/art_dex_file_loader.h"
34 #include "dex/compact_dex_level.h"
35 #include "obj_ptr-inl.h"
36 
37 namespace art {
38 
39 using LogSeverity = android::base::LogSeverity;
40 using ScopedLogSeverity = android::base::ScopedLogSeverity;
41 
42 template<class MirrorType>
MakeObjPtr(MirrorType * ptr)43 static inline ObjPtr<MirrorType> MakeObjPtr(MirrorType* ptr) {
44   return ptr;
45 }
46 
47 template<class MirrorType>
MakeObjPtr(ObjPtr<MirrorType> ptr)48 static inline ObjPtr<MirrorType> MakeObjPtr(ObjPtr<MirrorType> ptr) {
49   return ptr;
50 }
51 
52 // OBJ pointer helpers to avoid needing .Decode everywhere.
53 #define EXPECT_OBJ_PTR_EQ(a, b) EXPECT_EQ(MakeObjPtr(a).Ptr(), MakeObjPtr(b).Ptr())
54 #define ASSERT_OBJ_PTR_EQ(a, b) ASSERT_EQ(MakeObjPtr(a).Ptr(), MakeObjPtr(b).Ptr())
55 #define EXPECT_OBJ_PTR_NE(a, b) EXPECT_NE(MakeObjPtr(a).Ptr(), MakeObjPtr(b).Ptr())
56 #define ASSERT_OBJ_PTR_NE(a, b) ASSERT_NE(MakeObjPtr(a).Ptr(), MakeObjPtr(b).Ptr())
57 
58 class DexFile;
59 
60 class ScratchFile {
61  public:
62   ScratchFile();
63 
64   explicit ScratchFile(const std::string& filename);
65 
66   ScratchFile(const ScratchFile& other, const char* suffix);
67 
68   ScratchFile(ScratchFile&& other) noexcept;
69 
70   ScratchFile& operator=(ScratchFile&& other) noexcept;
71 
72   explicit ScratchFile(File* file);
73 
74   ~ScratchFile();
75 
GetFilename()76   const std::string& GetFilename() const {
77     return filename_;
78   }
79 
GetFile()80   File* GetFile() const {
81     return file_.get();
82   }
83 
84   int GetFd() const;
85 
86   void Close();
87   void Unlink();
88 
89  private:
90   std::string filename_;
91   std::unique_ptr<File> file_;
92 };
93 
94 class CommonArtTestImpl {
95  public:
96   CommonArtTestImpl() = default;
97   virtual ~CommonArtTestImpl() = default;
98 
99   // Set up ANDROID_BUILD_TOP, ANDROID_HOST_OUT, ANDROID_ROOT, ANDROID_RUNTIME_ROOT,
100   // and ANDROID_TZDATA_ROOT environment variables using sensible defaults if not already set.
101   static void SetUpAndroidRootEnvVars();
102 
103   // Set up the ANDROID_DATA environment variable, creating the directory if required.
104   // Note: setting up ANDROID_DATA may create a temporary directory. If this is used in a
105   // non-derived class, be sure to also call the corresponding tear-down below.
106   static void SetUpAndroidDataDir(std::string& android_data);
107 
108   static void TearDownAndroidDataDir(const std::string& android_data, bool fail_on_error);
109 
110   // Get the names of the libcore modules.
111   virtual std::vector<std::string> GetLibCoreModuleNames() const;
112 
113   // Gets the paths of the libcore dex files for given modules.
114   std::vector<std::string> GetLibCoreDexFileNames(const std::vector<std::string>& modules) const;
115 
116   // Gets the paths of the libcore dex files.
117   std::vector<std::string> GetLibCoreDexFileNames() const;
118 
119   // Gets the locations of the libcore dex files for given modules.
120   std::vector<std::string> GetLibCoreDexLocations(const std::vector<std::string>& modules) const;
121 
122   // Gets the locations of the libcore dex files.
123   std::vector<std::string> GetLibCoreDexLocations() const;
124 
125   static std::string GetClassPathOption(const char* option,
126                                         const std::vector<std::string>& class_path);
127 
128   // Returns bin directory which contains host's prebuild tools.
129   static std::string GetAndroidHostToolsDir();
130 
131   // Retuerns the filename for a test dex (i.e. XandY or ManyMethods).
132   std::string GetTestDexFileName(const char* name) const;
133 
134   template <typename Mutator>
MutateDexFile(File * output_dex,const std::string & input_jar,const Mutator & mutator)135   bool MutateDexFile(File* output_dex, const std::string& input_jar, const Mutator& mutator) {
136     std::vector<std::unique_ptr<const DexFile>> dex_files;
137     std::string error_msg;
138     const ArtDexFileLoader dex_file_loader;
139     CHECK(dex_file_loader.Open(input_jar.c_str(),
140                                input_jar.c_str(),
141                                /*verify*/ true,
142                                /*verify_checksum*/ true,
143                                &error_msg,
144                                &dex_files)) << error_msg;
145     EXPECT_EQ(dex_files.size(), 1u) << "Only one input dex is supported";
146     const std::unique_ptr<const DexFile>& dex = dex_files[0];
147     CHECK(dex->EnableWrite()) << "Failed to enable write";
148     DexFile* dex_file = const_cast<DexFile*>(dex.get());
149     mutator(dex_file);
150     const_cast<DexFile::Header&>(dex_file->GetHeader()).checksum_ = dex_file->CalculateChecksum();
151     if (!output_dex->WriteFully(dex->Begin(), dex->Size())) {
152       return false;
153     }
154     if (output_dex->Flush() != 0) {
155       PLOG(FATAL) << "Could not flush the output file.";
156     }
157     return true;
158   }
159 
160   struct ForkAndExecResult {
161     enum Stage {
162       kLink,
163       kFork,
164       kWaitpid,
165       kFinished,
166     };
167     Stage stage;
168     int status_code;
169 
StandardSuccessForkAndExecResult170     bool StandardSuccess() {
171       return stage == kFinished && WIFEXITED(status_code) && WEXITSTATUS(status_code) == 0;
172     }
173   };
174   using OutputHandlerFn = std::function<void(char*, size_t)>;
175   using PostForkFn = std::function<bool()>;
176   static ForkAndExecResult ForkAndExec(const std::vector<std::string>& argv,
177                                        const PostForkFn& post_fork,
178                                        const OutputHandlerFn& handler);
179   static ForkAndExecResult ForkAndExec(const std::vector<std::string>& argv,
180                                        const PostForkFn& post_fork,
181                                        std::string* output);
182 
183  protected:
IsHost()184   static bool IsHost() {
185     return !kIsTargetBuild;
186   }
187 
188   // Helper - find directory with the following format:
189   // ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
190   static std::string GetAndroidToolsDir(const std::string& subdir1,
191                                         const std::string& subdir2,
192                                         const std::string& subdir3);
193 
194   // File location to core.art, e.g. $ANDROID_HOST_OUT/system/framework/core.art
195   static std::string GetCoreArtLocation();
196 
197   // File location to core.oat, e.g. $ANDROID_HOST_OUT/system/framework/core.oat
198   static std::string GetCoreOatLocation();
199 
200   std::unique_ptr<const DexFile> LoadExpectSingleDexFile(const char* location);
201 
202   void ClearDirectory(const char* dirpath, bool recursive = true);
203 
204   std::string GetTestAndroidRoot();
205 
206   // Open a file (allows reading of framework jars).
207   std::vector<std::unique_ptr<const DexFile>> OpenDexFiles(const char* filename);
208 
209   // Open a single dex file (aborts if there are more than one).
210   std::unique_ptr<const DexFile> OpenDexFile(const char* filename);
211 
212   // Open a test file (art-gtest-*.jar).
213   std::vector<std::unique_ptr<const DexFile>> OpenTestDexFiles(const char* name);
214 
215   std::unique_ptr<const DexFile> OpenTestDexFile(const char* name);
216 
217 
218   std::string android_data_;
219   std::string dalvik_cache_;
220 
221   virtual void SetUp();
222 
223   virtual void TearDown();
224 
225   // Creates the class path string for the given dex files (the list of dex file locations
226   // separated by ':').
227   std::string CreateClassPath(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
228   // Same as CreateClassPath but add the dex file checksum after each location. The separator
229   // is '*'.
230   std::string CreateClassPathWithChecksums(
231       const std::vector<std::unique_ptr<const DexFile>>& dex_files);
232 
233   static std::string GetCoreFileLocation(const char* suffix);
234 
235   std::vector<std::unique_ptr<const DexFile>> loaded_dex_files_;
236 };
237 
238 template <typename TestType>
239 class CommonArtTestBase : public TestType, public CommonArtTestImpl {
240  public:
CommonArtTestBase()241   CommonArtTestBase() {}
~CommonArtTestBase()242   virtual ~CommonArtTestBase() {}
243 
244  protected:
SetUp()245   void SetUp() override {
246     CommonArtTestImpl::SetUp();
247   }
248 
TearDown()249   void TearDown() override {
250     CommonArtTestImpl::TearDown();
251   }
252 };
253 
254 using CommonArtTest = CommonArtTestBase<testing::Test>;
255 
256 template <typename Param>
257 using CommonArtTestWithParam = CommonArtTestBase<testing::TestWithParam<Param>>;
258 
259 #define TEST_DISABLED_FOR_TARGET() \
260   if (kIsTargetBuild) { \
261     printf("WARNING: TEST DISABLED FOR TARGET\n"); \
262     return; \
263   }
264 
265 #define TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS() \
266   if (!kHostStaticBuildEnabled) { \
267     printf("WARNING: TEST DISABLED FOR NON-STATIC HOST BUILDS\n"); \
268     return; \
269   }
270 
271 #define TEST_DISABLED_FOR_MEMORY_TOOL() \
272   if (kRunningOnMemoryTool) { \
273     printf("WARNING: TEST DISABLED FOR MEMORY TOOL\n"); \
274     return; \
275   }
276 
277 #define TEST_DISABLED_FOR_HEAP_POISONING() \
278   if (kPoisonHeapReferences) { \
279     printf("WARNING: TEST DISABLED FOR HEAP POISONING\n"); \
280     return; \
281   }
282 }  // namespace art
283 
284 #define TEST_DISABLED_FOR_MEMORY_TOOL_WITH_HEAP_POISONING() \
285   if (kRunningOnMemoryTool && kPoisonHeapReferences) { \
286     printf("WARNING: TEST DISABLED FOR MEMORY TOOL WITH HEAP POISONING\n"); \
287     return; \
288   }
289 
290 #endif  // ART_LIBARTBASE_BASE_COMMON_ART_TEST_H_
291