You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
7.4 KiB
198 lines
7.4 KiB
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <android-base/file.h>
|
|
#include <android-base/strings.h>
|
|
|
|
#include "environment.h"
|
|
#include "read_elf.h"
|
|
#include "utils.h"
|
|
#include "workload.h"
|
|
|
|
using namespace simpleperf;
|
|
|
|
static const std::string SLEEP_SEC = "0.001";
|
|
|
|
void RunWorkloadFunction();
|
|
void CreateProcesses(size_t count, std::vector<std::unique_ptr<Workload>>* workloads);
|
|
|
|
void ParseSymbol(const ElfFileSymbol& symbol, std::map<std::string, ElfFileSymbol>* symbols);
|
|
void CheckElfFileSymbols(const std::map<std::string, ElfFileSymbol>& symbols);
|
|
|
|
#define TEST_IN_ROOT(TestStatement) \
|
|
do { \
|
|
if (IsRoot()) { \
|
|
TestStatement; \
|
|
} else { \
|
|
GTEST_LOG_(INFO) << "Didn't test \"" << #TestStatement << "\" requires root privileges"; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define TEST_REQUIRE_ROOT() \
|
|
do { \
|
|
if (!IsRoot()) { \
|
|
GTEST_LOG_(INFO) << "Skip this test as it needs root privileges."; \
|
|
return; \
|
|
} \
|
|
} while (0)
|
|
|
|
#define TEST_REQUIRE_NON_ROOT() \
|
|
do { \
|
|
if (IsRoot()) { \
|
|
GTEST_LOG_(INFO) << "Skip this test as it tests non-root behavior."; \
|
|
return; \
|
|
} \
|
|
} while (0)
|
|
|
|
#if defined(__ANDROID__)
|
|
#define TEST_REQUIRE_HOST_ROOT()
|
|
#else
|
|
#define TEST_REQUIRE_HOST_ROOT() TEST_REQUIRE_ROOT()
|
|
#endif
|
|
|
|
bool IsInNativeAbi();
|
|
// Used to skip tests not supposed to run on non-native ABIs.
|
|
#define OMIT_TEST_ON_NON_NATIVE_ABIS() \
|
|
do { \
|
|
if (!IsInNativeAbi()) { \
|
|
GTEST_LOG_(INFO) << "Skip this test as it only runs on native ABIs."; \
|
|
return; \
|
|
} \
|
|
} while (0)
|
|
|
|
bool HasHardwareCounter();
|
|
#define TEST_REQUIRE_HW_COUNTER() \
|
|
do { \
|
|
if (!HasHardwareCounter()) { \
|
|
GTEST_LOG_(INFO) << "Skip this test as the machine doesn't have hardware PMU counters."; \
|
|
return; \
|
|
} \
|
|
} while (0)
|
|
|
|
bool HasPmuCounter();
|
|
#define TEST_REQUIRE_PMU_COUNTER() \
|
|
do { \
|
|
if (!HasPmuCounter()) { \
|
|
GTEST_LOG_(INFO) << "Skip this test as the machine doesn't have low-level PMU counters."; \
|
|
return; \
|
|
} \
|
|
} while (0)
|
|
|
|
bool HasTracepointEvents();
|
|
#define TEST_REQUIRE_TRACEPOINT_EVENTS() \
|
|
do { \
|
|
if (!HasTracepointEvents()) { \
|
|
GTEST_LOG_(INFO) << "Skip this test as the machine doesn't support tracepoint events."; \
|
|
return; \
|
|
} \
|
|
} while (0)
|
|
|
|
#if defined(IN_CTS_TEST)
|
|
#define TEST_REQUIRE_APPS()
|
|
#else
|
|
#define TEST_REQUIRE_APPS() \
|
|
do { \
|
|
GTEST_LOG_(INFO) << "Skip this test as test apps aren't available."; \
|
|
return; \
|
|
} while (0)
|
|
#endif
|
|
|
|
class CaptureStdout {
|
|
public:
|
|
CaptureStdout() : started_(false) {}
|
|
|
|
~CaptureStdout() {
|
|
if (started_) {
|
|
Finish();
|
|
}
|
|
}
|
|
|
|
bool Start() {
|
|
fflush(stdout);
|
|
old_stdout_ = dup(STDOUT_FILENO);
|
|
if (old_stdout_ == -1) {
|
|
return false;
|
|
}
|
|
started_ = true;
|
|
tmpfile_.reset(new TemporaryFile);
|
|
if (dup2(tmpfile_->fd, STDOUT_FILENO) == -1) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::string Finish() {
|
|
fflush(stdout);
|
|
started_ = false;
|
|
dup2(old_stdout_, STDOUT_FILENO);
|
|
close(old_stdout_);
|
|
std::string s;
|
|
if (!android::base::ReadFileToString(tmpfile_->path, &s)) {
|
|
return "";
|
|
}
|
|
return s;
|
|
}
|
|
|
|
private:
|
|
bool started_;
|
|
int old_stdout_;
|
|
std::unique_ptr<TemporaryFile> tmpfile_;
|
|
};
|
|
|
|
class AppHelper {
|
|
public:
|
|
~AppHelper() {
|
|
for (auto& package : installed_packages_) {
|
|
Workload::RunCmd({"pm", "uninstall", package});
|
|
}
|
|
}
|
|
|
|
bool InstallApk(const std::string& apk_path, const std::string& package_name) {
|
|
if (Workload::RunCmd({"pm", "install", "-t", "--abi", GetABI(), apk_path})) {
|
|
installed_packages_.emplace_back(package_name);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool StartApp(const std::string& start_cmd) {
|
|
app_start_proc_ = Workload::CreateWorkload(android::base::Split(start_cmd, " "));
|
|
return app_start_proc_ && app_start_proc_->Start();
|
|
}
|
|
|
|
private:
|
|
const char* GetABI() {
|
|
#if defined(__i386__)
|
|
return "x86";
|
|
#elif defined(__x86_64__)
|
|
return "x86_64";
|
|
#elif defined(__aarch64__)
|
|
return "arm64-v8a";
|
|
#elif defined(__arm__)
|
|
return "armeabi-v7a";
|
|
#else
|
|
#error "unrecognized ABI"
|
|
#endif
|
|
}
|
|
|
|
std::vector<std::string> installed_packages_;
|
|
std::unique_ptr<Workload> app_start_proc_;
|
|
}; |