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