diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2017-07-15 05:18:31 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2017-07-15 05:18:31 +0000 |
commit | 9bc17045b0f10379d9e2ef1723c08c9079df03b8 (patch) | |
tree | cf7de582ecda3ec87fe4a9f35b71f55aa996fe56 | |
parent | 9aa1dc2f3039db9faee9d581360a5d65caddb8f4 (diff) | |
parent | 616b3a020bf708f364e0608107ded083930ac6b4 (diff) | |
download | extras-9bc17045b0f10379d9e2ef1723c08c9079df03b8.tar.gz |
Merge "simpleperf: change the way running cts tests."
-rw-r--r-- | simpleperf/Android.mk | 2 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 1 | ||||
-rw-r--r-- | simpleperf/cmd_record_test.cpp | 4 | ||||
-rw-r--r-- | simpleperf/cmd_stat.cpp | 1 | ||||
-rw-r--r-- | simpleperf/cmd_stat_test.cpp | 27 | ||||
-rw-r--r-- | simpleperf/command.cpp | 48 | ||||
-rw-r--r-- | simpleperf/command.h | 1 | ||||
-rw-r--r-- | simpleperf/environment.cpp | 10 | ||||
-rw-r--r-- | simpleperf/environment.h | 4 | ||||
-rw-r--r-- | simpleperf/gtest_main.cpp | 91 | ||||
-rw-r--r-- | simpleperf/main.cpp | 52 | ||||
-rw-r--r-- | simpleperf/test_util.h | 1 | ||||
-rw-r--r-- | simpleperf/workload.cpp | 14 | ||||
-rw-r--r-- | simpleperf/workload.h | 16 |
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); }; |