diff options
Diffstat (limited to 'simpleperf/cmd_report_test.cpp')
-rw-r--r-- | simpleperf/cmd_report_test.cpp | 143 |
1 files changed, 89 insertions, 54 deletions
diff --git a/simpleperf/cmd_report_test.cpp b/simpleperf/cmd_report_test.cpp index e112d0d0..fb79c931 100644 --- a/simpleperf/cmd_report_test.cpp +++ b/simpleperf/cmd_report_test.cpp @@ -16,10 +16,12 @@ #include <gtest/gtest.h> +#include <regex> #include <set> #include <unordered_map> #include <android-base/file.h> +#include <android-base/parseint.h> #include <android-base/strings.h> #include "command.h" @@ -28,25 +30,25 @@ #include "read_apk.h" #include "test_util.h" +using namespace simpleperf; + static std::unique_ptr<Command> ReportCmd() { return CreateCommandInstance("report"); } class ReportCommandTest : public ::testing::Test { protected: - void Report( - const std::string& perf_data, - const std::vector<std::string>& add_args = std::vector<std::string>()) { + void Report(const std::string& perf_data, + const std::vector<std::string>& add_args = std::vector<std::string>()) { ReportRaw(GetTestData(perf_data), add_args); } - void ReportRaw( - const std::string& perf_data, - const std::vector<std::string>& add_args = std::vector<std::string>()) { + void ReportRaw(const std::string& perf_data, + const std::vector<std::string>& add_args = std::vector<std::string>()) { success = false; TemporaryFile tmp_file; - std::vector<std::string> args = { - "-i", perf_data, "--symfs", GetTestDataDir(), "-o", tmp_file.path}; + std::vector<std::string> args = {"-i", perf_data, "--symfs", GetTestDataDir(), + "-o", tmp_file.path}; args.insert(args.end(), add_args.begin(), add_args.end()); ASSERT_TRUE(ReportCmd()->Run(args)); ASSERT_TRUE(android::base::ReadFileToString(tmp_file.path, &content)); @@ -63,6 +65,17 @@ class ReportCommandTest : public ::testing::Test { success = true; } + size_t GetSampleCount() { + std::smatch m; + if (std::regex_search(content, m, std::regex(R"(Samples: (\d+))"))) { + size_t count; + if (android::base::ParseUint(m[1], &count)) { + return count; + } + } + return 0; + } + std::string content; std::vector<std::string> lines; bool success; @@ -84,8 +97,7 @@ TEST_F(ReportCommandTest, sort_option_pid) { Report(PERF_DATA, {"--sort", "pid"}); ASSERT_TRUE(success); size_t line_index = 0; - while (line_index < lines.size() && - lines[line_index].find("Pid") == std::string::npos) { + while (line_index < lines.size() && lines[line_index].find("Pid") == std::string::npos) { line_index++; } ASSERT_LT(line_index + 2, lines.size()); @@ -95,8 +107,7 @@ TEST_F(ReportCommandTest, sort_option_more_than_one) { Report(PERF_DATA, {"--sort", "comm,pid,dso,symbol"}); ASSERT_TRUE(success); size_t line_index = 0; - while (line_index < lines.size() && - lines[line_index].find("Overhead") == std::string::npos) { + while (line_index < lines.size() && lines[line_index].find("Overhead") == std::string::npos) { line_index++; } ASSERT_LT(line_index + 1, lines.size()); @@ -114,8 +125,7 @@ TEST_F(ReportCommandTest, children_option) { for (size_t i = 0; i < lines.size(); ++i) { char name[1024]; std::pair<double, double> pair; - if (sscanf(lines[i].c_str(), "%lf%%%lf%%%s", &pair.first, &pair.second, - name) == 3) { + if (sscanf(lines[i].c_str(), "%lf%%%lf%%%s", &pair.first, &pair.second, name) == 3) { map.insert(std::make_pair(name, pair)); } } @@ -167,8 +177,7 @@ TEST_F(ReportCommandTest, callgraph_option) { static bool AllItemsWithString(std::vector<std::string>& lines, const std::vector<std::string>& strs) { size_t line_index = 0; - while (line_index < lines.size() && - lines[line_index].find("Overhead") == std::string::npos) { + while (line_index < lines.size() && lines[line_index].find("Overhead") == std::string::npos) { line_index++; } if (line_index == lines.size() || line_index + 1 == lines.size()) { @@ -195,19 +204,16 @@ TEST_F(ReportCommandTest, pid_filter_option) { ASSERT_TRUE(success); ASSERT_FALSE(AllItemsWithString(lines, {"17441"})); ASSERT_FALSE(AllItemsWithString(lines, {"17441", "17443"})); - Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, - {"--sort", "pid", "--pids", "17441"}); + Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "pid", "--pids", "17441"}); ASSERT_TRUE(success); ASSERT_TRUE(AllItemsWithString(lines, {"17441"})); - Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, - {"--sort", "pid", "--pids", "17441,17443"}); + Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "pid", "--pids", "17441,17443"}); ASSERT_TRUE(success); ASSERT_TRUE(AllItemsWithString(lines, {"17441", "17443"})); // Test that --pids option is not the same as --tids option. // Thread 17445 and 17441 are in process 17441. - Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, - {"--sort", "tid", "--pids", "17441"}); + Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "tid", "--pids", "17441"}); ASSERT_TRUE(success); ASSERT_NE(content.find("17441"), std::string::npos); ASSERT_NE(content.find("17445"), std::string::npos); @@ -219,7 +225,7 @@ TEST_F(ReportCommandTest, wrong_pid_filter_option) { Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--pids", "2,bogus"}); exit(success ? 0 : 1); }, - testing::ExitedWithCode(1), "invalid id in --pids option: bogus"); + testing::ExitedWithCode(1), "Invalid tid 'bogus'"); } TEST_F(ReportCommandTest, tid_filter_option) { @@ -227,12 +233,10 @@ TEST_F(ReportCommandTest, tid_filter_option) { ASSERT_TRUE(success); ASSERT_FALSE(AllItemsWithString(lines, {"17441"})); ASSERT_FALSE(AllItemsWithString(lines, {"17441", "17445"})); - Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, - {"--sort", "tid", "--tids", "17441"}); + Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "tid", "--tids", "17441"}); ASSERT_TRUE(success); ASSERT_TRUE(AllItemsWithString(lines, {"17441"})); - Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, - {"--sort", "tid", "--tids", "17441,17445"}); + Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--sort", "tid", "--tids", "17441,17445"}); ASSERT_TRUE(success); ASSERT_TRUE(AllItemsWithString(lines, {"17441", "17445"})); } @@ -243,7 +247,7 @@ TEST_F(ReportCommandTest, wrong_tid_filter_option) { Report(PERF_DATA_WITH_MULTIPLE_PIDS_AND_TIDS, {"--tids", "2,bogus"}); exit(success ? 0 : 1); }, - testing::ExitedWithCode(1), "invalid id in --tids option: bogus"); + testing::ExitedWithCode(1), "Invalid tid 'bogus'"); } TEST_F(ReportCommandTest, comm_filter_option) { @@ -277,12 +281,10 @@ TEST_F(ReportCommandTest, symbol_filter_option) { ASSERT_TRUE(success); ASSERT_FALSE(AllItemsWithString(lines, {"func2(int, int)"})); ASSERT_FALSE(AllItemsWithString(lines, {"main", "func2(int, int)"})); - Report(PERF_DATA_WITH_SYMBOLS, - {"--sort", "symbol", "--symbols", "func2(int, int)"}); + Report(PERF_DATA_WITH_SYMBOLS, {"--sort", "symbol", "--symbols", "func2(int, int)"}); ASSERT_TRUE(success); ASSERT_TRUE(AllItemsWithString(lines, {"func2(int, int)"})); - Report(PERF_DATA_WITH_SYMBOLS, - {"--sort", "symbol", "--symbols", "main;func2(int, int)"}); + Report(PERF_DATA_WITH_SYMBOLS, {"--sort", "symbol", "--symbols", "main;func2(int, int)"}); ASSERT_TRUE(success); ASSERT_TRUE(AllItemsWithString(lines, {"main", "func2(int, int)"})); } @@ -302,19 +304,16 @@ TEST_F(ReportCommandTest, use_branch_address) { } } } - ASSERT_NE(hit_set.find(std::make_pair<std::string, std::string>( - "GlobalFunc", "CalledFunc")), + ASSERT_NE(hit_set.find(std::make_pair<std::string, std::string>("GlobalFunc", "CalledFunc")), hit_set.end()); - ASSERT_NE(hit_set.find(std::make_pair<std::string, std::string>( - "CalledFunc", "GlobalFunc")), + ASSERT_NE(hit_set.find(std::make_pair<std::string, std::string>("CalledFunc", "GlobalFunc")), hit_set.end()); } TEST_F(ReportCommandTest, report_symbols_of_nativelib_in_apk) { Report(NATIVELIB_IN_APK_PERF_DATA); ASSERT_TRUE(success); - ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)), - std::string::npos); + ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)), std::string::npos); ASSERT_NE(content.find("Func2"), std::string::npos); } @@ -362,8 +361,7 @@ TEST_F(ReportCommandTest, report_sort_vaddr_in_file) { } TEST_F(ReportCommandTest, check_build_id) { - Report(PERF_DATA_FOR_BUILD_ID_CHECK, - {"--symfs", GetTestData(CORRECT_SYMFS_FOR_BUILD_ID_CHECK)}); + Report(PERF_DATA_FOR_BUILD_ID_CHECK, {"--symfs", GetTestData(CORRECT_SYMFS_FOR_BUILD_ID_CHECK)}); ASSERT_TRUE(success); ASSERT_NE(content.find("main"), std::string::npos); ASSERT_EXIT( @@ -393,8 +391,7 @@ TEST_F(ReportCommandTest, no_show_ip_option) { TEST_F(ReportCommandTest, no_symbol_table_warning) { ASSERT_EXIT( { - Report(PERF_DATA, - {"--symfs", GetTestData(SYMFS_FOR_NO_SYMBOL_TABLE_WARNING)}); + Report(PERF_DATA, {"--symfs", GetTestData(SYMFS_FOR_NO_SYMBOL_TABLE_WARNING)}); if (!success) { exit(1); } @@ -409,8 +406,7 @@ TEST_F(ReportCommandTest, no_symbol_table_warning) { TEST_F(ReportCommandTest, read_elf_file_warning) { ASSERT_EXIT( { - Report(PERF_DATA, - {"--symfs", GetTestData(SYMFS_FOR_READ_ELF_FILE_WARNING)}); + Report(PERF_DATA, {"--symfs", GetTestData(SYMFS_FOR_READ_ELF_FILE_WARNING)}); if (!success) { exit(1); } @@ -439,12 +435,10 @@ TEST_F(ReportCommandTest, max_stack_and_percent_limit_option) { ASSERT_TRUE(success); ASSERT_NE(content.find("89.03"), std::string::npos); - Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT, - {"-g", "--percent-limit", "90"}); + Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT, {"-g", "--percent-limit", "90"}); ASSERT_TRUE(success); ASSERT_EQ(content.find("89.03"), std::string::npos); - Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT, - {"-g", "--percent-limit", "70"}); + Report(PERF_DATA_MAX_STACK_AND_PERCENT_LIMIT, {"-g", "--percent-limit", "70"}); ASSERT_TRUE(success); ASSERT_NE(content.find("89.03"), std::string::npos); } @@ -495,6 +489,49 @@ TEST_F(ReportCommandTest, report_big_trace_data) { ASSERT_TRUE(success); } +TEST_F(ReportCommandTest, csv_option) { + Report(PERF_DATA, {"--csv"}); + ASSERT_TRUE(success); + ASSERT_NE(content.find("EventCount,EventName"), std::string::npos); + + Report(CALLGRAPH_FP_PERF_DATA, {"--children", "--csv"}); + ASSERT_TRUE(success); + ASSERT_NE(content.find("AccEventCount,SelfEventCount,EventName"), std::string::npos); +} + +TEST_F(ReportCommandTest, dso_path_for_jit_cache) { + Report("perf_with_jit_symbol.data", {"--sort", "dso"}); + ASSERT_TRUE(success); + ASSERT_NE(content.find("[JIT app cache]"), std::string::npos); + + // Check if we can filter dso by "[JIT app cache]". + Report("perf_with_jit_symbol.data", {"--dsos", "[JIT app cache]"}); + ASSERT_TRUE(success); + ASSERT_NE(content.find("[JIT app cache]"), std::string::npos); +} + +TEST_F(ReportCommandTest, generic_jit_symbols) { + Report("perf_with_generic_git_symbols.data", {"--sort", "symbol"}); + ASSERT_TRUE(success); + ASSERT_NE(std::string::npos, content.find("generic_jit_symbol_one")); +} + +TEST_F(ReportCommandTest, cpu_option) { + Report("perf.data"); + ASSERT_TRUE(success); + ASSERT_EQ(2409, GetSampleCount()); + Report("perf.data", {"--cpu", "2"}); + ASSERT_TRUE(success); + ASSERT_EQ(603, GetSampleCount()); + Report("perf.data", {"--cpu", "2-6,16"}); + ASSERT_TRUE(success); + ASSERT_EQ(1806, GetSampleCount()); + Report("perf.data", {"--cpu", "2-6", "--cpu", "16"}); + ASSERT_TRUE(success); + ASSERT_EQ(1806, GetSampleCount()); + ASSERT_FALSE(ReportCmd()->Run({"-i", GetTestData("perf.data"), "--cpu", "-2"})); +} + #if defined(__linux__) #include "event_selection_set.h" @@ -510,16 +547,14 @@ TEST_F(ReportCommandTest, dwarf_callgraph) { CreateProcesses(1, &workloads); std::string pid = std::to_string(workloads[0]->GetPid()); TemporaryFile tmp_file; - ASSERT_TRUE( - RecordCmd()->Run({"-p", pid, "-g", "-o", tmp_file.path, "sleep", SLEEP_SEC})); + ASSERT_TRUE(RecordCmd()->Run({"-p", pid, "-g", "-o", tmp_file.path, "sleep", SLEEP_SEC})); ReportRaw(tmp_file.path, {"-g"}); ASSERT_TRUE(success); } TEST_F(ReportCommandTest, report_dwarf_callgraph_of_nativelib_in_apk) { Report(NATIVELIB_IN_APK_PERF_DATA, {"-g"}); - ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)), - std::string::npos); + ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)), std::string::npos); ASSERT_NE(content.find("Func2"), std::string::npos); ASSERT_NE(content.find("Func1"), std::string::npos); ASSERT_NE(content.find("GlobalFunc"), std::string::npos); @@ -533,8 +568,8 @@ TEST_F(ReportCommandTest, exclude_kernel_callchain) { CreateProcesses(1, &workloads); std::string pid = std::to_string(workloads[0]->GetPid()); TemporaryFile tmpfile; - ASSERT_TRUE(RecordCmd()->Run({"--trace-offcpu", "-e", "cpu-cycles:u", "-p", pid, - "--duration", "2", "-o", tmpfile.path, "-g"})); + ASSERT_TRUE(RecordCmd()->Run({"--trace-offcpu", "-e", "cpu-cycles:u", "-p", pid, "--duration", + "2", "-o", tmpfile.path, "-g"})); ReportRaw(tmpfile.path, {"-g"}); ASSERT_TRUE(success); ASSERT_EQ(content.find("[kernel.kallsyms]"), std::string::npos); |