blob: e0b35bf0342d3655c4fce71a998fa9243a0c9d83 [file] [log] [blame]
Yabin Cui2672dea2015-05-21 12:17:23 -07001/*
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 <gtest/gtest.h>
18
Yabin Cui6e51bef2016-02-23 21:41:03 -080019#include <set>
20#include <unordered_map>
21
Yabin Cuib1a885b2016-02-14 19:18:02 -080022#include <android-base/file.h>
Yabin Cui6e51bef2016-02-23 21:41:03 -080023#include <android-base/strings.h>
Yabin Cuib1a885b2016-02-14 19:18:02 -080024#include <android-base/test_utils.h>
25
Yabin Cui2672dea2015-05-21 12:17:23 -070026#include "command.h"
Yabin Cui19e6b6d2016-03-10 11:49:57 -080027#include "event_selection_set.h"
Yabin Cuib1a885b2016-02-14 19:18:02 -080028#include "get_test_data.h"
Yabin Cui8f680f62016-03-18 18:47:43 -070029#include "perf_regs.h"
Yabin Cuib1a885b2016-02-14 19:18:02 -080030#include "read_apk.h"
Yabin Cui6e51bef2016-02-23 21:41:03 -080031#include "test_util.h"
Yabin Cui2672dea2015-05-21 12:17:23 -070032
33static std::unique_ptr<Command> ReportCmd() {
34 return CreateCommandInstance("report");
35}
36
37class ReportCommandTest : public ::testing::Test {
38 protected:
Yabin Cui767dd172016-06-02 21:02:43 -070039 void Report(
40 const std::string perf_data,
41 const std::vector<std::string>& add_args = std::vector<std::string>()) {
Yabin Cui6e51bef2016-02-23 21:41:03 -080042 ReportRaw(GetTestData(perf_data), add_args);
Yabin Cui2672dea2015-05-21 12:17:23 -070043 }
Yabin Cui6e51bef2016-02-23 21:41:03 -080044
Yabin Cui767dd172016-06-02 21:02:43 -070045 void ReportRaw(
46 const std::string perf_data,
47 const std::vector<std::string>& add_args = std::vector<std::string>()) {
Yabin Cui6e51bef2016-02-23 21:41:03 -080048 success = false;
Yabin Cui767dd172016-06-02 21:02:43 -070049 std::vector<std::string> args = {
50 "-i", perf_data, "--symfs", GetTestDataDir(), "-o", tmp_file.path};
Yabin Cui6e51bef2016-02-23 21:41:03 -080051 args.insert(args.end(), add_args.begin(), add_args.end());
52 ASSERT_TRUE(ReportCmd()->Run(args));
53 ASSERT_TRUE(android::base::ReadFileToString(tmp_file.path, &content));
54 ASSERT_TRUE(!content.empty());
55 std::vector<std::string> raw_lines = android::base::Split(content, "\n");
56 lines.clear();
57 for (const auto& line : raw_lines) {
58 std::string s = android::base::Trim(line);
59 if (!s.empty()) {
60 lines.push_back(s);
61 }
62 }
63 ASSERT_GE(lines.size(), 2u);
64 success = true;
65 }
66
67 TemporaryFile tmp_file;
68 std::string content;
69 std::vector<std::string> lines;
70 bool success;
Yabin Cui2672dea2015-05-21 12:17:23 -070071};
72
Yabin Cui6e51bef2016-02-23 21:41:03 -080073TEST_F(ReportCommandTest, no_option) {
74 Report(PERF_DATA);
75 ASSERT_TRUE(success);
76 ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
Yabin Cui2672dea2015-05-21 12:17:23 -070077}
78
Yabin Cui05400532016-03-17 21:18:53 -070079TEST_F(ReportCommandTest, report_symbol_from_elf_file_with_mini_debug_info) {
80 Report(PERF_DATA_WITH_MINI_DEBUG_INFO);
81 ASSERT_TRUE(success);
82 ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
83}
84
Yabin Cui2672dea2015-05-21 12:17:23 -070085TEST_F(ReportCommandTest, sort_option_pid) {
Yabin Cui6e51bef2016-02-23 21:41:03 -080086 Report(PERF_DATA, {"--sort", "pid"});
87 ASSERT_TRUE(success);
88 size_t line_index = 0;
Yabin Cui767dd172016-06-02 21:02:43 -070089 while (line_index < lines.size() &&
90 lines[line_index].find("Pid") == std::string::npos) {
Yabin Cui6e51bef2016-02-23 21:41:03 -080091 line_index++;
92 }
93 ASSERT_LT(line_index + 2, lines.size());
Yabin Cui2672dea2015-05-21 12:17:23 -070094}
95
Yabin Cui6e51bef2016-02-23 21:41:03 -080096TEST_F(ReportCommandTest, sort_option_more_than_one) {
97 Report(PERF_DATA, {"--sort", "comm,pid,dso,symbol"});
98 ASSERT_TRUE(success);
99 size_t line_index = 0;
Yabin Cui767dd172016-06-02 21:02:43 -0700100 while (line_index < lines.size() &&
101 lines[line_index].find("Overhead") == std::string::npos) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800102 line_index++;
103 }
104 ASSERT_LT(line_index + 1, lines.size());
105 ASSERT_NE(lines[line_index].find("Command"), std::string::npos);
106 ASSERT_NE(lines[line_index].find("Pid"), std::string::npos);
107 ASSERT_NE(lines[line_index].find("Shared Object"), std::string::npos);
108 ASSERT_NE(lines[line_index].find("Symbol"), std::string::npos);
109 ASSERT_EQ(lines[line_index].find("Tid"), std::string::npos);
Yabin Cui2672dea2015-05-21 12:17:23 -0700110}
Yabin Cui8a530e32015-06-23 20:42:01 -0700111
Yabin Cuiecb9a302015-07-01 10:00:52 -0700112TEST_F(ReportCommandTest, children_option) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800113 Report(CALLGRAPH_FP_PERF_DATA, {"--children", "--sort", "symbol"});
114 ASSERT_TRUE(success);
115 std::unordered_map<std::string, std::pair<double, double>> map;
116 for (size_t i = 0; i < lines.size(); ++i) {
117 char name[1024];
118 std::pair<double, double> pair;
Yabin Cui767dd172016-06-02 21:02:43 -0700119 if (sscanf(lines[i].c_str(), "%lf%%%lf%%%s", &pair.first, &pair.second,
120 name) == 3) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800121 map.insert(std::make_pair(name, pair));
122 }
123 }
124 ASSERT_NE(map.find("GlobalFunc"), map.end());
125 ASSERT_NE(map.find("main"), map.end());
126 auto func_pair = map["GlobalFunc"];
127 auto main_pair = map["main"];
128 ASSERT_GE(main_pair.first, func_pair.first);
129 ASSERT_GE(func_pair.first, func_pair.second);
130 ASSERT_GE(func_pair.second, main_pair.second);
131}
132
133static bool CheckCalleeMode(std::vector<std::string>& lines) {
134 bool found = false;
135 for (size_t i = 0; i + 2 < lines.size(); ++i) {
136 if (lines[i].find("GlobalFunc") != std::string::npos &&
137 lines[i + 1].find("|") != std::string::npos &&
138 lines[i + 2].find("main") != std::string::npos) {
139 found = true;
140 break;
141 }
142 }
143 return found;
144}
145
146static bool CheckCallerMode(std::vector<std::string>& lines) {
147 bool found = false;
148 for (size_t i = 0; i + 2 < lines.size(); ++i) {
149 if (lines[i].find("main") != std::string::npos &&
150 lines[i + 1].find("|") != std::string::npos &&
151 lines[i + 2].find("GlobalFunc") != std::string::npos) {
152 found = true;
153 break;
154 }
155 }
156 return found;
Yabin Cuiecb9a302015-07-01 10:00:52 -0700157}
158
159TEST_F(ReportCommandTest, callgraph_option) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800160 Report(CALLGRAPH_FP_PERF_DATA, {"-g"});
161 ASSERT_TRUE(success);
Yabin Cui8a599d72016-07-21 18:32:53 -0700162 ASSERT_TRUE(CheckCallerMode(lines));
Yabin Cui6e51bef2016-02-23 21:41:03 -0800163 Report(CALLGRAPH_FP_PERF_DATA, {"-g", "callee"});
164 ASSERT_TRUE(success);
165 ASSERT_TRUE(CheckCalleeMode(lines));
166 Report(CALLGRAPH_FP_PERF_DATA, {"-g", "caller"});
167 ASSERT_TRUE(success);
168 ASSERT_TRUE(CheckCallerMode(lines));
169}
170
Yabin Cui767dd172016-06-02 21:02:43 -0700171static bool AllItemsWithString(std::vector<std::string>& lines,
172 const std::vector<std::string>& strs) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800173 size_t line_index = 0;
Yabin Cui767dd172016-06-02 21:02:43 -0700174 while (line_index < lines.size() &&
175 lines[line_index].find("Overhead") == std::string::npos) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800176 line_index++;
177 }
178 if (line_index == lines.size() || line_index + 1 == lines.size()) {
179 return false;
180 }
181 line_index++;
182 for (; line_index < lines.size(); ++line_index) {
183 bool exist = false;
184 for (auto& s : strs) {
185 if (lines[line_index].find(s) != std::string::npos) {
186 exist = true;
187 break;
188 }
189 }
190 if (!exist) {
191 return false;
192 }
193 }
194 return true;
Yabin Cuiecb9a302015-07-01 10:00:52 -0700195}
196
Yabin Cui38e573e2015-08-06 11:25:09 -0700197TEST_F(ReportCommandTest, pid_filter_option) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800198 Report(PERF_DATA);
199 ASSERT_TRUE("success");
200 ASSERT_FALSE(AllItemsWithString(lines, {"26083"}));
201 ASSERT_FALSE(AllItemsWithString(lines, {"26083", "26090"}));
202 Report(PERF_DATA, {"--pids", "26083"});
203 ASSERT_TRUE(success);
204 ASSERT_TRUE(AllItemsWithString(lines, {"26083"}));
205 Report(PERF_DATA, {"--pids", "26083,26090"});
206 ASSERT_TRUE(success);
207 ASSERT_TRUE(AllItemsWithString(lines, {"26083", "26090"}));
Yabin Cui38e573e2015-08-06 11:25:09 -0700208}
209
210TEST_F(ReportCommandTest, tid_filter_option) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800211 Report(PERF_DATA);
212 ASSERT_TRUE("success");
213 ASSERT_FALSE(AllItemsWithString(lines, {"26083"}));
214 ASSERT_FALSE(AllItemsWithString(lines, {"26083", "26090"}));
215 Report(PERF_DATA, {"--tids", "26083"});
216 ASSERT_TRUE(success);
217 ASSERT_TRUE(AllItemsWithString(lines, {"26083"}));
218 Report(PERF_DATA, {"--tids", "26083,26090"});
219 ASSERT_TRUE(success);
220 ASSERT_TRUE(AllItemsWithString(lines, {"26083", "26090"}));
Yabin Cui38e573e2015-08-06 11:25:09 -0700221}
222
223TEST_F(ReportCommandTest, comm_filter_option) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800224 Report(PERF_DATA, {"--sort", "comm"});
225 ASSERT_TRUE(success);
226 ASSERT_FALSE(AllItemsWithString(lines, {"t1"}));
227 ASSERT_FALSE(AllItemsWithString(lines, {"t1", "t2"}));
228 Report(PERF_DATA, {"--sort", "comm", "--comms", "t1"});
229 ASSERT_TRUE(success);
230 ASSERT_TRUE(AllItemsWithString(lines, {"t1"}));
231 Report(PERF_DATA, {"--sort", "comm", "--comms", "t1,t2"});
232 ASSERT_TRUE(success);
233 ASSERT_TRUE(AllItemsWithString(lines, {"t1", "t2"}));
Yabin Cui38e573e2015-08-06 11:25:09 -0700234}
235
236TEST_F(ReportCommandTest, dso_filter_option) {
Yabin Cui6e51bef2016-02-23 21:41:03 -0800237 Report(PERF_DATA, {"--sort", "dso"});
238 ASSERT_TRUE(success);
239 ASSERT_FALSE(AllItemsWithString(lines, {"/t1"}));
240 ASSERT_FALSE(AllItemsWithString(lines, {"/t1", "/t2"}));
241 Report(PERF_DATA, {"--sort", "dso", "--dsos", "/t1"});
242 ASSERT_TRUE(success);
243 ASSERT_TRUE(AllItemsWithString(lines, {"/t1"}));
244 Report(PERF_DATA, {"--sort", "dso", "--dsos", "/t1,/t2"});
245 ASSERT_TRUE(success);
246 ASSERT_TRUE(AllItemsWithString(lines, {"/t1", "/t2"}));
Yabin Cui38e573e2015-08-06 11:25:09 -0700247}
248
Yabin Cuif79fbd12016-07-06 12:26:13 -0700249TEST_F(ReportCommandTest, symbol_filter_option) {
250 Report(PERF_DATA_WITH_SYMBOLS, {"--sort", "symbol"});
251 ASSERT_TRUE(success);
Yabin Cui05ef2ea2016-07-11 13:50:01 -0700252 ASSERT_FALSE(AllItemsWithString(lines, {"func2(int, int)"}));
253 ASSERT_FALSE(AllItemsWithString(lines, {"main", "func2(int, int)"}));
Yabin Cuif79fbd12016-07-06 12:26:13 -0700254 Report(PERF_DATA_WITH_SYMBOLS,
Yabin Cui05ef2ea2016-07-11 13:50:01 -0700255 {"--sort", "symbol", "--symbols", "func2(int, int)"});
Yabin Cuif79fbd12016-07-06 12:26:13 -0700256 ASSERT_TRUE(success);
Yabin Cui05ef2ea2016-07-11 13:50:01 -0700257 ASSERT_TRUE(AllItemsWithString(lines, {"func2(int, int)"}));
Yabin Cuif79fbd12016-07-06 12:26:13 -0700258 Report(PERF_DATA_WITH_SYMBOLS,
Yabin Cui05ef2ea2016-07-11 13:50:01 -0700259 {"--sort", "symbol", "--symbols", "main;func2(int, int)"});
Yabin Cuif79fbd12016-07-06 12:26:13 -0700260 ASSERT_TRUE(success);
Yabin Cui05ef2ea2016-07-11 13:50:01 -0700261 ASSERT_TRUE(AllItemsWithString(lines, {"main", "func2(int, int)"}));
Yabin Cuif79fbd12016-07-06 12:26:13 -0700262}
263
Yabin Cui6e51bef2016-02-23 21:41:03 -0800264TEST_F(ReportCommandTest, use_branch_address) {
265 Report(BRANCH_PERF_DATA, {"-b", "--sort", "symbol_from,symbol_to"});
266 std::set<std::pair<std::string, std::string>> hit_set;
267 bool after_overhead = false;
268 for (const auto& line : lines) {
269 if (!after_overhead && line.find("Overhead") != std::string::npos) {
270 after_overhead = true;
271 } else if (after_overhead) {
272 char from[80];
273 char to[80];
274 if (sscanf(line.c_str(), "%*f%%%s%s", from, to) == 2) {
275 hit_set.insert(std::make_pair<std::string, std::string>(from, to));
276 }
277 }
Yabin Cui8a530e32015-06-23 20:42:01 -0700278 }
Yabin Cui767dd172016-06-02 21:02:43 -0700279 ASSERT_NE(hit_set.find(std::make_pair<std::string, std::string>(
280 "GlobalFunc", "CalledFunc")),
Yabin Cui6e51bef2016-02-23 21:41:03 -0800281 hit_set.end());
Yabin Cui767dd172016-06-02 21:02:43 -0700282 ASSERT_NE(hit_set.find(std::make_pair<std::string, std::string>(
283 "CalledFunc", "GlobalFunc")),
Yabin Cui6e51bef2016-02-23 21:41:03 -0800284 hit_set.end());
Yabin Cui8a530e32015-06-23 20:42:01 -0700285}
Yabin Cui3c8c2132015-08-13 20:30:20 -0700286
Yabin Cui8f680f62016-03-18 18:47:43 -0700287TEST_F(ReportCommandTest, report_symbols_of_nativelib_in_apk) {
288 Report(NATIVELIB_IN_APK_PERF_DATA);
289 ASSERT_TRUE(success);
Yabin Cui767dd172016-06-02 21:02:43 -0700290 ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)),
291 std::string::npos);
Yabin Cui8f680f62016-03-18 18:47:43 -0700292 ASSERT_NE(content.find("Func2"), std::string::npos);
293}
294
Yabin Cui2d6efe42016-04-01 20:22:35 -0700295TEST_F(ReportCommandTest, report_more_than_one_event_types) {
296 Report(PERF_DATA_WITH_TWO_EVENT_TYPES);
297 ASSERT_TRUE(success);
298 ASSERT_NE(content.find("cpu-cycles"), std::string::npos);
299 ASSERT_NE(content.find("cpu-clock"), std::string::npos);
300}
301
Yabin Cuib4212972016-05-25 14:08:05 -0700302TEST_F(ReportCommandTest, report_kernel_symbol) {
303 Report(PERF_DATA_WITH_KERNEL_SYMBOL);
304 ASSERT_TRUE(success);
Yabin Cui1761a272016-06-23 17:11:14 -0700305 ASSERT_NE(content.find("perf_event_aux"), std::string::npos);
Yabin Cuib4212972016-05-25 14:08:05 -0700306}
307
Yabin Cui767dd172016-06-02 21:02:43 -0700308TEST_F(ReportCommandTest, report_dumped_symbols) {
309 Report(PERF_DATA_WITH_SYMBOLS);
310 ASSERT_TRUE(success);
Yabin Cui05ef2ea2016-07-11 13:50:01 -0700311 ASSERT_NE(content.find("main"), std::string::npos);
Yabin Cuic855ecc2016-07-11 17:04:54 -0700312 Report(PERF_DATA_WITH_SYMBOLS_FOR_NONZERO_MINVADDR_DSO);
313 ASSERT_TRUE(success);
314 ASSERT_NE(content.find("main"), std::string::npos);
Yabin Cui767dd172016-06-02 21:02:43 -0700315}
316
Yabin Cui9970a232016-06-29 12:18:11 -0700317TEST_F(ReportCommandTest, report_sort_vaddr_in_file) {
318 Report(PERF_DATA, {"--sort", "vaddr_in_file"});
319 ASSERT_TRUE(success);
320 ASSERT_NE(content.find("VaddrInFile"), std::string::npos);
321}
322
Yabin Cuieec606c2016-07-07 13:53:33 -0700323TEST_F(ReportCommandTest, check_build_id) {
324 Report(PERF_DATA_FOR_BUILD_ID_CHECK,
325 {"--symfs", GetTestData(CORRECT_SYMFS_FOR_BUILD_ID_CHECK)});
326 ASSERT_TRUE(success);
327 ASSERT_NE(content.find("main"), std::string::npos);
328 ASSERT_EXIT(
329 {
330 Report(PERF_DATA_FOR_BUILD_ID_CHECK,
331 {"--symfs", GetTestData(WRONG_SYMFS_FOR_BUILD_ID_CHECK)});
332 if (!success) {
333 exit(1);
334 }
335 if (content.find("main") != std::string::npos) {
336 exit(2);
337 }
338 exit(0);
339 },
340 testing::ExitedWithCode(0), "build id.*mismatch");
341}
342
Yabin Cui15475e62016-07-14 13:26:19 -0700343TEST_F(ReportCommandTest, no_show_ip_option) {
344 Report(PERF_DATA);
345 ASSERT_TRUE(success);
346 ASSERT_EQ(content.find("unknown"), std::string::npos);
347 Report(PERF_DATA, {"--no-show-ip"});
348 ASSERT_TRUE(success);
349 ASSERT_NE(content.find("unknown"), std::string::npos);
350}
351
Yabin Cui19e6b6d2016-03-10 11:49:57 -0800352#if defined(__linux__)
Yabin Cui6e51bef2016-02-23 21:41:03 -0800353
354static std::unique_ptr<Command> RecordCmd() {
355 return CreateCommandInstance("record");
Yabin Cui3c8c2132015-08-13 20:30:20 -0700356}
Yabin Cuib1a885b2016-02-14 19:18:02 -0800357
Yabin Cui6e51bef2016-02-23 21:41:03 -0800358TEST_F(ReportCommandTest, dwarf_callgraph) {
Yabin Cui19e6b6d2016-03-10 11:49:57 -0800359 if (IsDwarfCallChainSamplingSupported()) {
360 TemporaryFile tmp_file;
Yabin Cui767dd172016-06-02 21:02:43 -0700361 ASSERT_TRUE(
362 RecordCmd()->Run({"-g", "-o", tmp_file.path, "sleep", SLEEP_SEC}));
Yabin Cui19e6b6d2016-03-10 11:49:57 -0800363 ReportRaw(tmp_file.path, {"-g"});
364 ASSERT_TRUE(success);
365 } else {
Yabin Cui767dd172016-06-02 21:02:43 -0700366 GTEST_LOG_(INFO) << "This test does nothing as dwarf callchain sampling is "
367 "not supported on this device.";
Yabin Cui19e6b6d2016-03-10 11:49:57 -0800368 }
Yabin Cui6e51bef2016-02-23 21:41:03 -0800369}
370
Yabin Cui8f680f62016-03-18 18:47:43 -0700371TEST_F(ReportCommandTest, report_dwarf_callgraph_of_nativelib_in_apk) {
Yabin Cui767dd172016-06-02 21:02:43 -0700372 // NATIVELIB_IN_APK_PERF_DATA is recorded on arm64, so can only report
373 // callgraph on arm64.
Yabin Cui8f680f62016-03-18 18:47:43 -0700374 if (GetBuildArch() == ARCH_ARM64) {
375 Report(NATIVELIB_IN_APK_PERF_DATA, {"-g"});
Yabin Cui767dd172016-06-02 21:02:43 -0700376 ASSERT_NE(content.find(GetUrlInApk(APK_FILE, NATIVELIB_IN_APK)),
377 std::string::npos);
Yabin Cui8f680f62016-03-18 18:47:43 -0700378 ASSERT_NE(content.find("Func2"), std::string::npos);
379 ASSERT_NE(content.find("Func1"), std::string::npos);
380 ASSERT_NE(content.find("GlobalFunc"), std::string::npos);
381 } else {
Yabin Cui767dd172016-06-02 21:02:43 -0700382 GTEST_LOG_(INFO)
383 << "This test does nothing as it is only run on arm64 devices";
Yabin Cui8f680f62016-03-18 18:47:43 -0700384 }
385}
386
Yabin Cui6e51bef2016-02-23 21:41:03 -0800387#endif