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