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