1 /* 2 * Copyright (C) 2015 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 #include <map> 18 #include <memory> 19 #include <optional> 20 #include <string> 21 #include <vector> 22 23 #include <android-base/file.h> 24 #include <android-base/strings.h> 25 26 #include "environment.h" 27 #include "read_elf.h" 28 #include "utils.h" 29 #include "workload.h" 30 31 using namespace simpleperf; 32 33 static const std::string SLEEP_SEC = "0.001"; 34 35 void RunWorkloadFunction(); 36 void CreateProcesses(size_t count, std::vector<std::unique_ptr<Workload>>* workloads); 37 38 void ParseSymbol(const ElfFileSymbol& symbol, std::map<std::string, ElfFileSymbol>* symbols); 39 void CheckElfFileSymbols(const std::map<std::string, ElfFileSymbol>& symbols); 40 41 #define TEST_IN_ROOT(TestStatement) \ 42 do { \ 43 if (IsRoot()) { \ 44 TestStatement; \ 45 } else { \ 46 GTEST_LOG_(INFO) << "Didn't test \"" << #TestStatement << "\" requires root privileges"; \ 47 } \ 48 } while (0) 49 50 #define TEST_REQUIRE_ROOT() \ 51 do { \ 52 if (!IsRoot()) { \ 53 GTEST_LOG_(INFO) << "Skip this test as it needs root privileges."; \ 54 return; \ 55 } \ 56 } while (0) 57 58 #define TEST_REQUIRE_NON_ROOT() \ 59 do { \ 60 if (IsRoot()) { \ 61 GTEST_LOG_(INFO) << "Skip this test as it tests non-root behavior."; \ 62 return; \ 63 } \ 64 } while (0) 65 66 #if defined(__ANDROID__) 67 #define TEST_REQUIRE_HOST_ROOT() 68 #else 69 #define TEST_REQUIRE_HOST_ROOT() TEST_REQUIRE_ROOT() 70 #endif 71 72 std::optional<bool> IsInNativeAbi(); 73 // Used to skip tests not supposed to run on non-native ABIs. 74 #define OMIT_TEST_ON_NON_NATIVE_ABIS() \ 75 do { \ 76 std::optional<bool> in_native_abi = IsInNativeAbi(); \ 77 ASSERT_TRUE(in_native_abi.has_value()); \ 78 if (!in_native_abi.value()) { \ 79 GTEST_LOG_(INFO) << "Skip this test as it only runs on native ABIs."; \ 80 return; \ 81 } \ 82 } while (0) 83 84 bool HasHardwareCounter(); 85 #define TEST_REQUIRE_HW_COUNTER() \ 86 do { \ 87 if (!HasHardwareCounter()) { \ 88 GTEST_LOG_(INFO) << "Skip this test as the machine doesn't have hardware PMU counters."; \ 89 return; \ 90 } \ 91 } while (0) 92 93 bool HasPmuCounter(); 94 #define TEST_REQUIRE_PMU_COUNTER() \ 95 do { \ 96 if (!HasPmuCounter()) { \ 97 GTEST_LOG_(INFO) << "Skip this test as the machine doesn't have low-level PMU counters."; \ 98 return; \ 99 } \ 100 } while (0) 101 102 bool HasTracepointEvents(); 103 #define TEST_REQUIRE_TRACEPOINT_EVENTS() \ 104 do { \ 105 if (!HasTracepointEvents()) { \ 106 GTEST_LOG_(INFO) << "Skip this test as the machine doesn't support tracepoint events."; \ 107 return; \ 108 } \ 109 } while (0) 110 111 #define TEST_REQUIRE_KERNEL_EVENTS() \ 112 do { \ 113 if (!IsKernelEventSupported()) { \ 114 GTEST_LOG_(INFO) << "Skip this test as the test environment can't count kernel events."; \ 115 return; \ 116 } \ 117 } while (0) 118 119 #if defined(IN_CTS_TEST) 120 #define TEST_REQUIRE_APPS() 121 #else 122 #define TEST_REQUIRE_APPS() \ 123 do { \ 124 GTEST_LOG_(INFO) << "Skip this test as test apps aren't available."; \ 125 return; \ 126 } while (0) 127 #endif 128 129 class CaptureStdout { 130 public: CaptureStdout()131 CaptureStdout() : started_(false) {} 132 ~CaptureStdout()133 ~CaptureStdout() { 134 if (started_) { 135 Finish(); 136 } 137 } 138 Start()139 bool Start() { 140 fflush(stdout); 141 old_stdout_ = dup(STDOUT_FILENO); 142 if (old_stdout_ == -1) { 143 return false; 144 } 145 started_ = true; 146 tmpfile_.reset(new TemporaryFile); 147 if (dup2(tmpfile_->fd, STDOUT_FILENO) == -1) { 148 return false; 149 } 150 return true; 151 } 152 Finish()153 std::string Finish() { 154 fflush(stdout); 155 started_ = false; 156 dup2(old_stdout_, STDOUT_FILENO); 157 close(old_stdout_); 158 std::string s; 159 if (!android::base::ReadFileToString(tmpfile_->path, &s)) { 160 return ""; 161 } 162 return s; 163 } 164 165 private: 166 bool started_; 167 int old_stdout_; 168 std::unique_ptr<TemporaryFile> tmpfile_; 169 }; 170 171 class AppHelper { 172 public: ~AppHelper()173 ~AppHelper() { 174 for (auto& package : installed_packages_) { 175 Workload::RunCmd({"pm", "uninstall", package}); 176 } 177 } 178 InstallApk(const std::string & apk_path,const std::string & package_name)179 bool InstallApk(const std::string& apk_path, const std::string& package_name) { 180 if (Workload::RunCmd({"pm", "install", "-t", "--abi", GetABI(), apk_path})) { 181 installed_packages_.emplace_back(package_name); 182 return true; 183 } 184 return false; 185 } 186 StartApp(const std::string & start_cmd)187 bool StartApp(const std::string& start_cmd) { 188 app_start_proc_ = Workload::CreateWorkload(android::base::Split(start_cmd, " ")); 189 return app_start_proc_ && app_start_proc_->Start(); 190 } 191 192 private: GetABI()193 const char* GetABI() { 194 #if defined(__i386__) 195 return "x86"; 196 #elif defined(__x86_64__) 197 return "x86_64"; 198 #elif defined(__aarch64__) 199 return "arm64-v8a"; 200 #elif defined(__arm__) 201 return "armeabi-v7a"; 202 #elif defined(__riscv) 203 return "riscv64"; 204 #else 205 #error "unrecognized ABI" 206 #endif 207 } 208 209 std::vector<std::string> installed_packages_; 210 std::unique_ptr<Workload> app_start_proc_; 211 }; 212 213 bool IsInEmulator(); 214