summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2017-07-15 05:18:31 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-07-15 05:18:31 +0000
commit9bc17045b0f10379d9e2ef1723c08c9079df03b8 (patch)
treecf7de582ecda3ec87fe4a9f35b71f55aa996fe56
parent9aa1dc2f3039db9faee9d581360a5d65caddb8f4 (diff)
parent616b3a020bf708f364e0608107ded083930ac6b4 (diff)
downloadextras-9bc17045b0f10379d9e2ef1723c08c9079df03b8.tar.gz
Merge "simpleperf: change the way running cts tests."
-rw-r--r--simpleperf/Android.mk2
-rw-r--r--simpleperf/cmd_record.cpp1
-rw-r--r--simpleperf/cmd_record_test.cpp4
-rw-r--r--simpleperf/cmd_stat.cpp1
-rw-r--r--simpleperf/cmd_stat_test.cpp27
-rw-r--r--simpleperf/command.cpp48
-rw-r--r--simpleperf/command.h1
-rw-r--r--simpleperf/environment.cpp10
-rw-r--r--simpleperf/environment.h4
-rw-r--r--simpleperf/gtest_main.cpp91
-rw-r--r--simpleperf/main.cpp52
-rw-r--r--simpleperf/test_util.h1
-rw-r--r--simpleperf/workload.cpp14
-rw-r--r--simpleperf/workload.h16
14 files changed, 154 insertions, 118 deletions
diff --git a/simpleperf/Android.mk b/simpleperf/Android.mk
index b1727464..d7c56f76 100644
--- a/simpleperf/Android.mk
+++ b/simpleperf/Android.mk
@@ -459,7 +459,7 @@ libsimpleperf_cts_test_src_files := \
include $(CLEAR_VARS)
LOCAL_CLANG := true
LOCAL_MODULE := libsimpleperf_cts_test
-LOCAL_CPPFLAGS := $(simpleperf_cppflags_target) -DRUN_IN_APP_CONTEXT
+LOCAL_CPPFLAGS := $(simpleperf_cppflags_target) -DRUN_IN_APP_CONTEXT="\"com.android.simpleperf\""
LOCAL_SRC_FILES := $(libsimpleperf_cts_test_src_files)
LOCAL_STATIC_LIBRARIES := $(simpleperf_static_libraries_target)
LOCAL_MULTILIB := both
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index e3f35c3d..d37c2a84 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -181,6 +181,7 @@ class RecordCommand : public Command {
in_app_context_(false) {
// Stop profiling if parent exits.
prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0);
+ app_package_name_ = GetDefaultAppPackageName();
}
bool Run(const std::vector<std::string>& args);
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp
index 468d36fd..fcedcee1 100644
--- a/simpleperf/cmd_record_test.cpp
+++ b/simpleperf/cmd_record_test.cpp
@@ -345,7 +345,7 @@ TEST(record_cmd, symfs_option) { ASSERT_TRUE(RunRecordCmd({"--symfs", "/"})); }
TEST(record_cmd, duration_option) {
TemporaryFile tmpfile;
ASSERT_TRUE(RecordCmd()->Run({"--duration", "1.2", "-p",
- std::to_string(getpid()), "-o", tmpfile.path}));
+ std::to_string(getpid()), "-o", tmpfile.path, "--in-app"}));
ASSERT_TRUE(
RecordCmd()->Run({"--duration", "1", "-o", tmpfile.path, "sleep", "2"}));
}
@@ -378,7 +378,7 @@ TEST(record_cmd, stop_when_no_more_targets) {
});
thread.detach();
while (tid == 0);
- ASSERT_TRUE(RecordCmd()->Run({"-o", tmpfile.path, "-t", std::to_string(tid)}));
+ ASSERT_TRUE(RecordCmd()->Run({"-o", tmpfile.path, "-t", std::to_string(tid), "--in-app"}));
}
TEST(record_cmd, donot_stop_when_having_targets) {
diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp
index c1f21f65..4c79801c 100644
--- a/simpleperf/cmd_stat.cpp
+++ b/simpleperf/cmd_stat.cpp
@@ -320,6 +320,7 @@ class StatCommand : public Command {
in_app_context_(false) {
// Die if parent exits.
prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0);
+ app_package_name_ = GetDefaultAppPackageName();
}
bool Run(const std::vector<std::string>& args);
diff --git a/simpleperf/cmd_stat_test.cpp b/simpleperf/cmd_stat_test.cpp
index 89e75f81..3cdb4ebd 100644
--- a/simpleperf/cmd_stat_test.cpp
+++ b/simpleperf/cmd_stat_test.cpp
@@ -55,18 +55,27 @@ TEST(stat_cmd, event_modifier) {
StatCmd()->Run({"-e", "cpu-cycles:u,cpu-cycles:k", "sleep", "1"}));
}
+void RunWorkloadFunction() {
+ while (true) {
+ for (volatile int i = 0; i < 10000; ++i);
+ usleep(1);
+ }
+}
+
void CreateProcesses(size_t count,
std::vector<std::unique_ptr<Workload>>* workloads) {
workloads->clear();
// Create workloads run longer than profiling time.
- auto function = []() {
- while (true) {
- for (volatile int i = 0; i < 10000; ++i);
- usleep(1);
- }
- };
for (size_t i = 0; i < count; ++i) {
- auto workload = Workload::CreateWorkload(function);
+ std::unique_ptr<Workload> workload;
+ if (GetDefaultAppPackageName().empty()) {
+ workload = Workload::CreateWorkload(RunWorkloadFunction);
+ } else {
+ workload = Workload::CreateWorkload({"run-as", GetDefaultAppPackageName(), "./workload"});
+ workload->SetKillFunction([](pid_t pid) {
+ Workload::RunCmd({"run-as", GetDefaultAppPackageName(), "kill", std::to_string(pid)});
+ });
+ }
ASSERT_TRUE(workload != nullptr);
ASSERT_TRUE(workload->Start());
workloads->push_back(std::move(workload));
@@ -117,7 +126,7 @@ TEST(stat_cmd, auto_generated_summary) {
TEST(stat_cmd, duration_option) {
ASSERT_TRUE(
- StatCmd()->Run({"--duration", "1.2", "-p", std::to_string(getpid())}));
+ StatCmd()->Run({"--duration", "1.2", "-p", std::to_string(getpid()), "--in-app"}));
ASSERT_TRUE(StatCmd()->Run({"--duration", "1", "sleep", "2"}));
}
@@ -164,5 +173,5 @@ TEST(stat_cmd, stop_when_no_more_targets) {
});
thread.detach();
while (tid == 0);
- ASSERT_TRUE(StatCmd()->Run({"-t", std::to_string(tid)}));
+ ASSERT_TRUE(StatCmd()->Run({"-t", std::to_string(tid), "--in-app"}));
}
diff --git a/simpleperf/command.cpp b/simpleperf/command.cpp
index f5d4e8bd..034163f9 100644
--- a/simpleperf/command.cpp
+++ b/simpleperf/command.cpp
@@ -23,6 +23,8 @@
#include <android-base/logging.h>
+#include "utils.h"
+
bool Command::NextArgumentOrError(const std::vector<std::string>& args, size_t* pi) {
if (*pi + 1 == args.size()) {
LOG(ERROR) << "No argument following " << args[*pi] << " option. Try `simpleperf help " << name_
@@ -95,3 +97,49 @@ class CommandRegister {
};
CommandRegister command_register;
+
+bool RunSimpleperfCmd(int argc, char** argv) {
+ android::base::InitLogging(argv, android::base::StderrLogger);
+ std::vector<std::string> args;
+ android::base::LogSeverity log_severity = android::base::INFO;
+
+ for (int i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
+ args.insert(args.begin(), "help");
+ } else if (strcmp(argv[i], "--log") == 0) {
+ if (i + 1 < argc) {
+ ++i;
+ if (!GetLogSeverity(argv[i], &log_severity)) {
+ LOG(ERROR) << "Unknown log severity: " << argv[i];
+ return false;
+ }
+ } else {
+ LOG(ERROR) << "Missing argument for --log option.\n";
+ return false;
+ }
+ } else if (strcmp(argv[i], "--version") == 0) {
+ LOG(INFO) << "Simpleperf version " << GetSimpleperfVersion();
+ return true;
+ } else {
+ args.push_back(argv[i]);
+ }
+ }
+ android::base::ScopedLogSeverity severity(log_severity);
+
+ if (args.empty()) {
+ args.push_back("help");
+ }
+ std::unique_ptr<Command> command = CreateCommandInstance(args[0]);
+ if (command == nullptr) {
+ LOG(ERROR) << "malformed command line: unknown command " << args[0];
+ return false;
+ }
+ std::string command_name = args[0];
+ args.erase(args.begin());
+
+ LOG(DEBUG) << "command '" << command_name << "' starts running";
+ bool result = command->Run(args);
+ LOG(DEBUG) << "command '" << command_name << "' "
+ << (result ? "finished successfully" : "failed");
+ return result;
+}
diff --git a/simpleperf/command.h b/simpleperf/command.h
index 2311f33a..6063dbf8 100644
--- a/simpleperf/command.h
+++ b/simpleperf/command.h
@@ -65,5 +65,6 @@ void RegisterCommand(const std::string& cmd_name,
void UnRegisterCommand(const std::string& cmd_name);
std::unique_ptr<Command> CreateCommandInstance(const std::string& cmd_name);
const std::vector<std::string> GetAllCommandNames();
+bool RunSimpleperfCmd(int argc, char** argv);
#endif // SIMPLE_PERF_COMMAND_H_
diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp
index 03fda1ac..e0027fc6 100644
--- a/simpleperf/environment.cpp
+++ b/simpleperf/environment.cpp
@@ -616,3 +616,13 @@ bool RunInAppContext(const std::string& app_package_name, const std::string& cmd
}
return true;
}
+
+static std::string default_package_name;
+
+void SetDefaultAppPackageName(const std::string& package_name) {
+ default_package_name = package_name;
+}
+
+const std::string& GetDefaultAppPackageName() {
+ return default_package_name;
+}
diff --git a/simpleperf/environment.h b/simpleperf/environment.h
index a2f0c4bd..603c9e60 100644
--- a/simpleperf/environment.h
+++ b/simpleperf/environment.h
@@ -96,4 +96,8 @@ bool RunInAppContext(const std::string& app_package_name, const std::string& cmd
const std::vector<std::string>& args, size_t workload_args_size,
const std::string& output_filepath);
+// Below two functions are only used in cts tests, to force stat/record cmd to run in app's context.
+void SetDefaultAppPackageName(const std::string& package_name);
+const std::string& GetDefaultAppPackageName();
+
#endif // SIMPLE_PERF_ENVIRONMENT_H_
diff --git a/simpleperf/gtest_main.cpp b/simpleperf/gtest_main.cpp
index 3cc929c8..42519d52 100644
--- a/simpleperf/gtest_main.cpp
+++ b/simpleperf/gtest_main.cpp
@@ -29,9 +29,13 @@
#include <sys/system_properties.h>
#endif
+#include "command.h"
+#include "environment.h"
#include "get_test_data.h"
#include "read_elf.h"
+#include "test_util.h"
#include "utils.h"
+#include "workload.h"
static std::string testdata_dir;
@@ -124,46 +128,52 @@ class ScopedEnablingPerf {
char prop_value_[PROP_VALUE_MAX];
};
-static bool TestInAppContext(int argc, char** argv) {
- // Use run-as to move the test executable to the data directory of debuggable app
- // 'com.android.simpleperf', and run it.
- std::string exe_path;
- if (!android::base::Readlink("/proc/self/exe", &exe_path)) {
- PLOG(ERROR) << "readlink failed";
- return false;
+class ScopedWorkloadExecutable {
+ public:
+ ScopedWorkloadExecutable() {
+ std::string executable_path;
+ if (!android::base::Readlink("/proc/self/exe", &executable_path)) {
+ PLOG(ERROR) << "ReadLink failed";
+ }
+ Workload::RunCmd({"run-as", GetDefaultAppPackageName(), "cp", executable_path, "workload"});
}
- std::string copy_cmd = android::base::StringPrintf("run-as com.android.simpleperf cp %s .",
- exe_path.c_str());
- if (system(copy_cmd.c_str()) == -1) {
- PLOG(ERROR) << "system(" << copy_cmd << ") failed";
- return false;
+
+ ~ScopedWorkloadExecutable() {
+ Workload::RunCmd({"run-as", GetDefaultAppPackageName(), "rm", "workload"});
}
- std::string arg_str;
- arg_str += basename(argv[0]);
- for (int i = 1; i < argc; ++i) {
- arg_str.push_back(' ');
- arg_str += argv[i];
- }
- std::string test_cmd = android::base::StringPrintf("run-as com.android.simpleperf ./%s",
- arg_str.c_str());
- test_cmd += " --in-app-context";
- if (system(test_cmd.c_str()) == -1) {
- PLOG(ERROR) << "system(" << test_cmd << ") failed";
- return false;
+};
+
+class ScopedTempDir {
+ public:
+ ~ScopedTempDir() {
+ Workload::RunCmd({"rm", "-rf", dir_.path});
}
- return true;
-}
+
+ char* path() {
+ return dir_.path;
+ }
+
+ private:
+ TemporaryDir dir_;
+};
#endif // defined(__ANDROID__)
int main(int argc, char** argv) {
android::base::InitLogging(argv, android::base::StderrLogger);
android::base::LogSeverity log_severity = android::base::WARNING;
- bool need_app_context __attribute__((unused)) = false;
- bool in_app_context __attribute__((unused)) = false;
#if defined(RUN_IN_APP_CONTEXT)
- need_app_context = true;
+ // When RUN_IN_APP_CONTEXT macro is defined, the tests running record/stat commands will
+ // be forced to run with '--app' option. It will copy the test binary to an Android application's
+ // directory, and use run-as to run the binary as simpleperf executable.
+ if (android::base::Basename(argv[0]) == "simpleperf") {
+ return RunSimpleperfCmd(argc, argv) ? 0 : 1;
+ } else if (android::base::Basename(argv[0]) == "workload") {
+ RunWorkloadFunction();
+ }
+ SetDefaultAppPackageName(RUN_IN_APP_CONTEXT);
+ ScopedWorkloadExecutable scoped_workload_executable;
#endif
for (int i = 1; i < argc; ++i) {
@@ -181,31 +191,22 @@ int main(int argc, char** argv) {
LOG(ERROR) << "Missing argument for --log option.\n";
return 1;
}
- } else if (strcmp(argv[i], "--in-app-context") == 0) {
- in_app_context = true;
}
}
android::base::ScopedLogSeverity severity(log_severity);
#if defined(__ANDROID__)
- std::unique_ptr<ScopedEnablingPerf> scoped_enabling_perf;
- if (!in_app_context) {
- // A cts test PerfEventParanoidTest.java is testing if
- // /proc/sys/kernel/perf_event_paranoid is 3, so restore perf_harden
- // value after current test to not break that test.
- scoped_enabling_perf.reset(new ScopedEnablingPerf);
- }
-
- if (need_app_context && !in_app_context) {
- return TestInAppContext(argc, argv) ? 0 : 1;
- }
+ // A cts test PerfEventParanoidTest.java is testing if
+ // /proc/sys/kernel/perf_event_paranoid is 3, so restore perf_harden
+ // value after current test to not break that test.
+ ScopedEnablingPerf scoped_enabling_perf;
- std::unique_ptr<TemporaryDir> tmp_dir;
+ std::unique_ptr<ScopedTempDir> tmp_dir;
if (!::testing::GTEST_FLAG(list_tests) && testdata_dir.empty()) {
testdata_dir = std::string(dirname(argv[0])) + "/testdata";
if (!IsDir(testdata_dir)) {
- tmp_dir.reset(new TemporaryDir);
- testdata_dir = std::string(tmp_dir->path) + "/";
+ tmp_dir.reset(new ScopedTempDir);
+ testdata_dir = std::string(tmp_dir->path()) + "/";
if (!ExtractTestDataFromElfSection()) {
LOG(ERROR) << "failed to extract test data from elf section";
return 1;
diff --git a/simpleperf/main.cpp b/simpleperf/main.cpp
index ae3e6292..d359dd13 100644
--- a/simpleperf/main.cpp
+++ b/simpleperf/main.cpp
@@ -14,58 +14,8 @@
* limitations under the License.
*/
-#include <string.h>
-
-#include <string>
-#include <vector>
-
-#include <android-base/logging.h>
-
#include "command.h"
-#include "utils.h"
int main(int argc, char** argv) {
- android::base::InitLogging(argv, android::base::StderrLogger);
- std::vector<std::string> args;
- android::base::LogSeverity log_severity = android::base::INFO;
-
- for (int i = 1; i < argc; ++i) {
- if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
- args.insert(args.begin(), "help");
- } else if (strcmp(argv[i], "--log") == 0) {
- if (i + 1 < argc) {
- ++i;
- if (!GetLogSeverity(argv[i], &log_severity)) {
- LOG(ERROR) << "Unknown log severity: " << argv[i];
- return 1;
- }
- } else {
- LOG(ERROR) << "Missing argument for --log option.\n";
- return 1;
- }
- } else if (strcmp(argv[i], "--version") == 0) {
- LOG(INFO) << "Simpleperf version " << GetSimpleperfVersion();
- return 0;
- } else {
- args.push_back(argv[i]);
- }
- }
- android::base::ScopedLogSeverity severity(log_severity);
-
- if (args.empty()) {
- args.push_back("help");
- }
- std::unique_ptr<Command> command = CreateCommandInstance(args[0]);
- if (command == nullptr) {
- LOG(ERROR) << "malformed command line: unknown command " << args[0];
- return 1;
- }
- std::string command_name = args[0];
- args.erase(args.begin());
-
- LOG(DEBUG) << "command '" << command_name << "' starts running";
- bool result = command->Run(args);
- LOG(DEBUG) << "command '" << command_name << "' "
- << (result ? "finished successfully" : "failed");
- return result ? 0 : 1;
+ return RunSimpleperfCmd(argc, argv) ? 0 : 1;
}
diff --git a/simpleperf/test_util.h b/simpleperf/test_util.h
index 15d11cb9..f242c896 100644
--- a/simpleperf/test_util.h
+++ b/simpleperf/test_util.h
@@ -24,6 +24,7 @@
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);
diff --git a/simpleperf/workload.cpp b/simpleperf/workload.cpp
index b3bd459f..4aaeb2a9 100644
--- a/simpleperf/workload.cpp
+++ b/simpleperf/workload.cpp
@@ -51,10 +51,22 @@ bool Workload::RunCmd(const std::vector<std::string>& args, bool report_error) {
return ret == 0;
}
+Workload::Workload(const std::vector<std::string>& args, const std::function<void ()>& function)
+ : work_state_(NotYetCreateNewProcess),
+ child_proc_args_(args),
+ child_proc_function_(function),
+ work_pid_(-1),
+ start_signal_fd_(-1),
+ exec_child_fd_(-1) {
+ kill_function_ = [](pid_t pid) {
+ kill(pid, SIGKILL);
+ };
+}
+
Workload::~Workload() {
if (work_pid_ != -1 && work_state_ != NotYetCreateNewProcess) {
if (!Workload::WaitChildProcess(false, false, nullptr)) {
- kill(work_pid_, SIGKILL);
+ kill_function_(work_pid_);
Workload::WaitChildProcess(true, true, nullptr);
}
}
diff --git a/simpleperf/workload.h b/simpleperf/workload.h
index 34fe7959..4ca93a42 100644
--- a/simpleperf/workload.h
+++ b/simpleperf/workload.h
@@ -51,17 +51,14 @@ class Workload {
bool WaitChildProcess(int* exit_code);
- private:
- explicit Workload(const std::vector<std::string>& args,
- const std::function<void ()>& function)
- : work_state_(NotYetCreateNewProcess),
- child_proc_args_(args),
- child_proc_function_(function),
- work_pid_(-1),
- start_signal_fd_(-1),
- exec_child_fd_(-1) {
+ // Set the function used to kill the workload process in ~Workload().
+ void SetKillFunction(const std::function<void (pid_t)>& kill_function) {
+ kill_function_ = kill_function;
}
+ private:
+ explicit Workload(const std::vector<std::string>& args, const std::function<void ()>& function);
+
bool CreateNewProcess();
void ChildProcessFn(int start_signal_fd, int exec_child_fd);
bool WaitChildProcess(bool wait_forever, bool is_child_killed, int* exit_code);
@@ -73,6 +70,7 @@ class Workload {
pid_t work_pid_;
int start_signal_fd_; // The parent process writes 1 to start workload in the child process.
int exec_child_fd_; // The child process writes 1 to notify that execvp() failed.
+ std::function<void (pid_t)> kill_function_;
DISALLOW_COPY_AND_ASSIGN(Workload);
};