• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sys/types.h>
21 #include <sys/wait.h>
22 
23 #include <functional>
24 #include <string>
25 #include <vector>
26 
27 #include "android-base/logging.h"
28 #include "android-base/properties.h"
29 #include "android-base/scopeguard.h"
30 #include "base/file_utils.h"
31 #include "base/globals.h"
32 #include "base/memory_tool.h"
33 #include "base/mutex.h"
34 #include "base/os.h"
35 #include "base/testing.h"
36 #include "base/unix_file/fd_file.h"
37 #include "dex/art_dex_file_loader.h"
38 #include "dex/compact_dex_file.h"
39 #include "gtest/gtest.h"
40 
41 namespace art {
42 
43 using LogSeverity = android::base::LogSeverity;
44 using ScopedLogSeverity = android::base::ScopedLogSeverity;
45 
46 class DexFile;
47 
48 class ScratchDir {
49  public:
50   explicit ScratchDir(bool keep_files = false);
51 
52   ~ScratchDir();
53 
GetPath()54   const std::string& GetPath() const {
55     return path_;
56   }
57 
58  private:
59   std::string path_;
60   bool keep_files_;  // Useful for debugging.
61 
62   DISALLOW_COPY_AND_ASSIGN(ScratchDir);
63 };
64 
65 class ScratchFile {
66  public:
67   ScratchFile();
68 
69   explicit ScratchFile(const std::string& filename);
70 
71   ScratchFile(const ScratchFile& other, const char* suffix);
72 
73   ScratchFile(ScratchFile&& other) noexcept;
74 
75   ScratchFile& operator=(ScratchFile&& other) noexcept;
76 
77   explicit ScratchFile(File* file);
78 
79   ~ScratchFile();
80 
GetFilename()81   const std::string& GetFilename() const {
82     return filename_;
83   }
84 
GetFile()85   File* GetFile() const {
86     return file_.get();
87   }
88 
89   int GetFd() const;
90 
91   void Close();
92   void Unlink();
93 
94  private:
95   std::string filename_;
96   std::unique_ptr<File> file_;
97 };
98 
99 // Helper class that removes an environment variable whilst in scope.
100 class ScopedUnsetEnvironmentVariable {
101  public:
ScopedUnsetEnvironmentVariable(const char * variable)102   explicit ScopedUnsetEnvironmentVariable(const char* variable)
103       : variable_{variable}, old_value_{GetOldValue(variable)} {
104     unsetenv(variable);
105   }
106 
~ScopedUnsetEnvironmentVariable()107   ~ScopedUnsetEnvironmentVariable() {
108     if (old_value_.has_value()) {
109       static constexpr int kReplace = 1;  // tidy-issue: replace argument has libc dependent name.
110       setenv(variable_, old_value_.value().c_str(), kReplace);
111     } else {
112       unsetenv(variable_);
113     }
114   }
115 
116  private:
GetOldValue(const char * variable)117   static std::optional<std::string> GetOldValue(const char* variable) {
118     const char* value = getenv(variable);
119     return value != nullptr ? std::optional<std::string>{value} : std::nullopt;
120   }
121 
122   const char* variable_;
123   std::optional<std::string> old_value_;
124   DISALLOW_COPY_AND_ASSIGN(ScopedUnsetEnvironmentVariable);
125 };
126 
127 // Temporarily drops all root capabilities when the test is run as root. This is a noop otherwise.
128 android::base::ScopeGuard<std::function<void()>> ScopedUnroot();
129 
130 // Temporarily drops all permissions on a file/directory.
131 android::base::ScopeGuard<std::function<void()>> ScopedInaccessible(const std::string& path);
132 
133 class CommonArtTestImpl {
134  public:
135   CommonArtTestImpl() = default;
136   virtual ~CommonArtTestImpl() = default;
137 
138   // Set up ANDROID_BUILD_TOP, ANDROID_HOST_OUT, ANDROID_ROOT, ANDROID_I18N_ROOT,
139   // ANDROID_ART_ROOT, and ANDROID_TZDATA_ROOT environment variables using sensible defaults
140   // if not already set.
141   static void SetUpAndroidRootEnvVars();
142 
143   // Set up the ANDROID_DATA environment variable, creating the directory if required.
144   // Note: setting up ANDROID_DATA may create a temporary directory. If this is used in a
145   // non-derived class, be sure to also call the corresponding tear-down below.
146   static void SetUpAndroidDataDir(std::string& android_data);
147 
148   static void TearDownAndroidDataDir(const std::string& android_data, bool fail_on_error);
149 
150   static void ClearDirectory(const char* dirpath, bool recursive = true);
151 
152   // Get the names of the libcore modules.
153   virtual std::vector<std::string> GetLibCoreModuleNames() const;
154 
155   // Gets the paths of the libcore dex files for given modules.
GetLibCoreDexFileNames(const std::vector<std::string> & modules)156   std::vector<std::string> GetLibCoreDexFileNames(const std::vector<std::string>& modules) const {
157     return art::testing::GetLibCoreDexFileNames(modules);
158   }
159 
160   // Gets the paths of the libcore dex files.
GetLibCoreDexFileNames()161   std::vector<std::string> GetLibCoreDexFileNames() const {
162     return GetLibCoreDexFileNames(GetLibCoreModuleNames());
163   }
164 
165   // Gets the on-host or on-device locations of the libcore dex files for given modules.
GetLibCoreDexLocations(const std::vector<std::string> & modules)166   std::vector<std::string> GetLibCoreDexLocations(const std::vector<std::string>& modules) const {
167     return art::testing::GetLibCoreDexLocations(modules);
168   }
169 
170   // Gets the on-host or on-device locations of the libcore dex files.
GetLibCoreDexLocations()171   std::vector<std::string> GetLibCoreDexLocations() const {
172     return GetLibCoreDexLocations(GetLibCoreModuleNames());
173   }
174 
GetClassPathOption(const char * option,const std::vector<std::string> & class_path)175   static std::string GetClassPathOption(const char* option,
176                                         const std::vector<std::string>& class_path) {
177     return art::testing::GetClassPathOption(option, class_path);
178   }
179 
180   // Retuerns the filename for a test dex (i.e. XandY or ManyMethods).
181   std::string GetTestDexFileName(const char* name) const;
182 
183   template <typename Mutator>
MutateDexFile(File * output_dex,const std::string & input_jar,const Mutator & mutator)184   bool MutateDexFile(File* output_dex, const std::string& input_jar, const Mutator& mutator) {
185     std::vector<std::unique_ptr<const DexFile>> dex_files;
186     std::string error_msg;
187     ArtDexFileLoader dex_file_loader(input_jar);
188     CHECK(dex_file_loader.Open(/*verify*/ true,
189                                /*verify_checksum*/ true,
190                                &error_msg,
191                                &dex_files))
192         << error_msg;
193     EXPECT_EQ(dex_files.size(), 1u) << "Only one input dex is supported";
194     const std::unique_ptr<const DexFile>& dex = dex_files[0];
195     CHECK(dex->EnableWrite()) << "Failed to enable write";
196     DexFile* dex_file = const_cast<DexFile*>(dex.get());
197     size_t original_size = dex_file->Size();
198     mutator(dex_file);
199     // NB: mutation might have changed the DEX size in the header.
200     std::vector<uint8_t> copy(dex_file->Begin(), dex_file->Begin() + original_size);
201     copy.resize(dex_file->Size());  // Shrink/expand to new size.
202     uint32_t checksum = DexFile::CalculateChecksum(copy.data(), copy.size());
203     CHECK_GE(copy.size(), sizeof(DexFile::Header));
204     reinterpret_cast<DexFile::Header*>(copy.data())->checksum_ = checksum;
205     if (!output_dex->WriteFully(copy.data(), copy.size())) {
206       return false;
207     }
208     if (output_dex->Flush() != 0) {
209       PLOG(FATAL) << "Could not flush the output file.";
210     }
211     return true;
212   }
213 
214   struct ForkAndExecResult {
215     enum Stage {
216       kLink,
217       kFork,
218       kWaitpid,
219       kFinished,
220     };
221     Stage stage;
222     int status_code;
223 
StandardSuccessForkAndExecResult224     bool StandardSuccess() {
225       return stage == kFinished && WIFEXITED(status_code) && WEXITSTATUS(status_code) == 0;
226     }
227   };
228   using OutputHandlerFn = std::function<void(char*, size_t)>;
229   using PostForkFn = std::function<bool()>;
230   static ForkAndExecResult ForkAndExec(const std::vector<std::string>& argv,
231                                        const PostForkFn& post_fork,
232                                        const OutputHandlerFn& handler);
233   static ForkAndExecResult ForkAndExec(const std::vector<std::string>& argv,
234                                        const PostForkFn& post_fork,
235                                        std::string* output);
236 
237   // Helper - find prebuilt tool (e.g. objdump).
238   static std::string GetAndroidTool(const char* name, InstructionSet isa = InstructionSet::kX86_64);
239 
240  protected:
IsHost()241   static bool IsHost() { return art::testing::IsHost(); }
242 
GetAndroidBuildTop()243   static std::string GetAndroidBuildTop() { return art::testing::GetAndroidBuildTop(); }
244 
GetAndroidHostOut()245   static std::string GetAndroidHostOut() { return art::testing::GetAndroidHostOut(); }
246 
GetHostBootClasspathInstallRoot()247   static std::string GetHostBootClasspathInstallRoot() {
248     return art::testing::GetHostBootClasspathInstallRoot();
249   }
250 
251   // File location to boot.art, e.g. /apex/com.android.art/javalib/boot.art
252   static std::string GetCoreArtLocation();
253 
254   // File location to boot.oat, e.g. /apex/com.android.art/javalib/boot.oat
255   static std::string GetCoreOatLocation();
256 
257   std::unique_ptr<const DexFile> LoadExpectSingleDexFile(const char* location);
258 
259   // Open a file (allows reading of framework jars).
260   std::vector<std::unique_ptr<const DexFile>> OpenDexFiles(const char* filename);
261 
262   // Open a single dex file (aborts if there are more than one).
263   std::unique_ptr<const DexFile> OpenDexFile(const char* filename);
264 
265   // Open a test file (art-gtest-*.jar).
266   std::vector<std::unique_ptr<const DexFile>> OpenTestDexFiles(const char* name);
267 
268   std::unique_ptr<const DexFile> OpenTestDexFile(const char* name);
269 
270   std::string android_data_;
271   std::string android_system_ext_;
272   std::string dalvik_cache_;
273 
274   virtual void SetUp();
275 
276   virtual void TearDown();
277 
278   // Creates the class path string for the given dex files (the list of dex file locations
279   // separated by ':').
280   std::string CreateClassPath(const std::vector<std::unique_ptr<const DexFile>>& dex_files);
281   // Same as CreateClassPath but add the dex file checksum after each location. The separator
282   // is '*'.
283   std::string CreateClassPathWithChecksums(
284       const std::vector<std::unique_ptr<const DexFile>>& dex_files);
285 
286   static std::string GetImageDirectory();
287   static std::string GetCoreFileLocation(const char* suffix);
288 
289   std::vector<std::unique_ptr<const DexFile>> loaded_dex_files_;
290 };
291 
292 template <typename TestType>
293 class CommonArtTestBase : public TestType, public CommonArtTestImpl {
294  public:
CommonArtTestBase()295   CommonArtTestBase() {}
~CommonArtTestBase()296   virtual ~CommonArtTestBase() {}
297 
298  protected:
SetUp()299   void SetUp() override {
300     CommonArtTestImpl::SetUp();
301   }
302 
TearDown()303   void TearDown() override {
304     CommonArtTestImpl::TearDown();
305   }
306 };
307 
308 using CommonArtTest = CommonArtTestBase<::testing::Test>;
309 
310 template <typename Param>
311 using CommonArtTestWithParam = CommonArtTestBase<::testing::TestWithParam<Param>>;
312 
313 // Returns a list of PIDs of the processes whose process name (the first commandline argument) fully
314 // matches the given name.
315 std::vector<pid_t> GetPidByName(const std::string& process_name);
316 
317 #define TEST_DISABLED_FOR_TARGET()                       \
318   if (art::kIsTargetBuild) {                                  \
319     GTEST_SKIP() << "WARNING: TEST DISABLED FOR TARGET"; \
320   }
321 
322 #define TEST_DISABLED_FOR_HOST()                       \
323   if (!art::kIsTargetBuild) {                               \
324     GTEST_SKIP() << "WARNING: TEST DISABLED FOR HOST"; \
325   }
326 
327 #define TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS()                       \
328   if (!art::kHostStaticBuildEnabled) {                                        \
329     GTEST_SKIP() << "WARNING: TEST DISABLED FOR NON-STATIC HOST BUILDS"; \
330   }
331 
332 #define TEST_DISABLED_FOR_DEBUG_BUILD()                       \
333   if (art::kIsDebugBuild) {                                        \
334     GTEST_SKIP() << "WARNING: TEST DISABLED FOR DEBUG BUILD"; \
335   }
336 
337 #define TEST_DISABLED_FOR_MEMORY_TOOL()                       \
338   if (art::kRunningOnMemoryTool) {                                 \
339     GTEST_SKIP() << "WARNING: TEST DISABLED FOR MEMORY TOOL"; \
340   }
341 
342 #define TEST_DISABLED_FOR_HEAP_POISONING()                       \
343   if (art::kPoisonHeapReferences) {                                   \
344     GTEST_SKIP() << "WARNING: TEST DISABLED FOR HEAP POISONING"; \
345   }
346 }  // namespace art
347 
348 #define TEST_DISABLED_FOR_MEMORY_TOOL_WITH_HEAP_POISONING()                       \
349   if (art::kRunningOnMemoryTool && art::kPoisonHeapReferences) {                            \
350     GTEST_SKIP() << "WARNING: TEST DISABLED FOR MEMORY TOOL WITH HEAP POISONING"; \
351   }
352 
353 #define TEST_DISABLED_FOR_USER_BUILD()                                          \
354   if (std::string build_type = android::base::GetProperty("ro.build.type", ""); \
355       art::kIsTargetBuild && build_type != "userdebug" && build_type != "eng") {     \
356     GTEST_SKIP() << "WARNING: TEST DISABLED FOR USER BUILD";                    \
357   }
358 
359 #endif  // ART_LIBARTBASE_BASE_COMMON_ART_TEST_H_
360