2 #include "util/debug.h"
3 #include "util/symbol.h"
5 #include "util/evsel.h"
6 #include "util/event.h"
7 #include "util/evlist.h"
8 #include "util/machine.h"
9 #include "util/thread.h"
10 #include "util/parse-events.h"
11 #include "tests/tests.h"
12 #include "tests/hists_common.h"
13 #include <linux/kernel.h>
18 struct thread
*thread
;
24 /* For the numbers, see hists_common.c */
25 static struct sample fake_samples
[] = {
26 /* perf [kernel] schedule() */
27 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_KERNEL_SCHEDULE
, .socket
= 0 },
28 /* perf [perf] main() */
29 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_PERF_MAIN
, .socket
= 0 },
30 /* perf [libc] malloc() */
31 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_LIBC_MALLOC
, .socket
= 0 },
32 /* perf [perf] main() */
33 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_PERF_MAIN
, .socket
= 0 }, /* will be merged */
34 /* perf [perf] cmd_record() */
35 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_PERF_CMD_RECORD
, .socket
= 1 },
36 /* perf [kernel] page_fault() */
37 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_KERNEL_PAGE_FAULT
, .socket
= 1 },
38 /* bash [bash] main() */
39 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_BASH_MAIN
, .socket
= 2 },
40 /* bash [bash] xmalloc() */
41 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_BASH_XMALLOC
, .socket
= 2 },
42 /* bash [libc] malloc() */
43 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_LIBC_MALLOC
, .socket
= 3 },
44 /* bash [kernel] page_fault() */
45 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_KERNEL_PAGE_FAULT
, .socket
= 3 },
48 static int add_hist_entries(struct perf_evlist
*evlist
,
49 struct machine
*machine
)
51 struct perf_evsel
*evsel
;
52 struct addr_location al
;
53 struct perf_sample sample
= { .period
= 100, };
57 * each evsel will have 10 samples but the 4th sample
58 * (perf [perf] main) will be collapsed to an existing entry
59 * so total 9 entries will be in the tree.
61 evlist__for_each_entry(evlist
, evsel
) {
62 for (i
= 0; i
< ARRAY_SIZE(fake_samples
); i
++) {
63 struct hist_entry_iter iter
= {
66 .ops
= &hist_iter_normal
,
67 .hide_unresolved
= false,
69 struct hists
*hists
= evsel__hists(evsel
);
71 /* make sure it has no filter at first */
72 hists
->thread_filter
= NULL
;
73 hists
->dso_filter
= NULL
;
74 hists
->symbol_filter_str
= NULL
;
76 sample
.cpumode
= PERF_RECORD_MISC_USER
;
77 sample
.pid
= fake_samples
[i
].pid
;
78 sample
.tid
= fake_samples
[i
].pid
;
79 sample
.ip
= fake_samples
[i
].ip
;
81 if (machine__resolve(machine
, &al
, &sample
) < 0)
84 al
.socket
= fake_samples
[i
].socket
;
85 if (hist_entry_iter__add(&iter
, &al
,
86 sysctl_perf_event_max_stack
, NULL
) < 0) {
87 addr_location__put(&al
);
91 fake_samples
[i
].thread
= al
.thread
;
92 fake_samples
[i
].map
= al
.map
;
93 fake_samples
[i
].sym
= al
.sym
;
100 pr_debug("Not enough memory for adding a hist entry\n");
104 int test__hists_filter(int subtest __maybe_unused
)
107 struct machines machines
;
108 struct machine
*machine
;
109 struct perf_evsel
*evsel
;
110 struct perf_evlist
*evlist
= perf_evlist__new();
112 TEST_ASSERT_VAL("No memory", evlist
);
114 err
= parse_events(evlist
, "cpu-clock", NULL
);
117 err
= parse_events(evlist
, "task-clock", NULL
);
122 /* default sort order (comm,dso,sym) will be used */
123 if (setup_sorting(NULL
) < 0)
126 machines__init(&machines
);
128 /* setup threads/dso/map/symbols also */
129 machine
= setup_fake_machine(&machines
);
134 machine__fprintf(machine
, stderr
);
136 /* process sample events */
137 err
= add_hist_entries(evlist
, machine
);
141 evlist__for_each_entry(evlist
, evsel
) {
142 struct hists
*hists
= evsel__hists(evsel
);
144 hists__collapse_resort(hists
, NULL
);
145 perf_evsel__output_resort(evsel
, NULL
);
148 pr_info("Normal histogram\n");
149 print_hists_out(hists
);
152 TEST_ASSERT_VAL("Invalid nr samples",
153 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
154 TEST_ASSERT_VAL("Invalid nr hist entries",
155 hists
->nr_entries
== 9);
156 TEST_ASSERT_VAL("Invalid total period",
157 hists
->stats
.total_period
== 1000);
158 TEST_ASSERT_VAL("Unmatched nr samples",
159 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] ==
160 hists
->stats
.nr_non_filtered_samples
);
161 TEST_ASSERT_VAL("Unmatched nr hist entries",
162 hists
->nr_entries
== hists
->nr_non_filtered_entries
);
163 TEST_ASSERT_VAL("Unmatched total period",
164 hists
->stats
.total_period
==
165 hists
->stats
.total_non_filtered_period
);
167 /* now applying thread filter for 'bash' */
168 hists
->thread_filter
= fake_samples
[9].thread
;
169 hists__filter_by_thread(hists
);
172 pr_info("Histogram for thread filter\n");
173 print_hists_out(hists
);
176 /* normal stats should be invariant */
177 TEST_ASSERT_VAL("Invalid nr samples",
178 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
179 TEST_ASSERT_VAL("Invalid nr hist entries",
180 hists
->nr_entries
== 9);
181 TEST_ASSERT_VAL("Invalid total period",
182 hists
->stats
.total_period
== 1000);
184 /* but filter stats are changed */
185 TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
186 hists
->stats
.nr_non_filtered_samples
== 4);
187 TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
188 hists
->nr_non_filtered_entries
== 4);
189 TEST_ASSERT_VAL("Unmatched total period for thread filter",
190 hists
->stats
.total_non_filtered_period
== 400);
192 /* remove thread filter first */
193 hists
->thread_filter
= NULL
;
194 hists__filter_by_thread(hists
);
196 /* now applying dso filter for 'kernel' */
197 hists
->dso_filter
= fake_samples
[0].map
->dso
;
198 hists__filter_by_dso(hists
);
201 pr_info("Histogram for dso filter\n");
202 print_hists_out(hists
);
205 /* normal stats should be invariant */
206 TEST_ASSERT_VAL("Invalid nr samples",
207 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
208 TEST_ASSERT_VAL("Invalid nr hist entries",
209 hists
->nr_entries
== 9);
210 TEST_ASSERT_VAL("Invalid total period",
211 hists
->stats
.total_period
== 1000);
213 /* but filter stats are changed */
214 TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
215 hists
->stats
.nr_non_filtered_samples
== 3);
216 TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
217 hists
->nr_non_filtered_entries
== 3);
218 TEST_ASSERT_VAL("Unmatched total period for dso filter",
219 hists
->stats
.total_non_filtered_period
== 300);
221 /* remove dso filter first */
222 hists
->dso_filter
= NULL
;
223 hists__filter_by_dso(hists
);
226 * now applying symbol filter for 'main'. Also note that
227 * there's 3 samples that have 'main' symbol but the 4th
228 * entry of fake_samples was collapsed already so it won't
229 * be counted as a separate entry but the sample count and
230 * total period will be remained.
232 hists
->symbol_filter_str
= "main";
233 hists__filter_by_symbol(hists
);
236 pr_info("Histogram for symbol filter\n");
237 print_hists_out(hists
);
240 /* normal stats should be invariant */
241 TEST_ASSERT_VAL("Invalid nr samples",
242 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
243 TEST_ASSERT_VAL("Invalid nr hist entries",
244 hists
->nr_entries
== 9);
245 TEST_ASSERT_VAL("Invalid total period",
246 hists
->stats
.total_period
== 1000);
248 /* but filter stats are changed */
249 TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
250 hists
->stats
.nr_non_filtered_samples
== 3);
251 TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
252 hists
->nr_non_filtered_entries
== 2);
253 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
254 hists
->stats
.total_non_filtered_period
== 300);
256 /* remove symbol filter first */
257 hists
->symbol_filter_str
= NULL
;
258 hists__filter_by_symbol(hists
);
260 /* now applying socket filters */
261 hists
->socket_filter
= 2;
262 hists__filter_by_socket(hists
);
265 pr_info("Histogram for socket filters\n");
266 print_hists_out(hists
);
269 /* normal stats should be invariant */
270 TEST_ASSERT_VAL("Invalid nr samples",
271 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
272 TEST_ASSERT_VAL("Invalid nr hist entries",
273 hists
->nr_entries
== 9);
274 TEST_ASSERT_VAL("Invalid total period",
275 hists
->stats
.total_period
== 1000);
277 /* but filter stats are changed */
278 TEST_ASSERT_VAL("Unmatched nr samples for socket filter",
279 hists
->stats
.nr_non_filtered_samples
== 2);
280 TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter",
281 hists
->nr_non_filtered_entries
== 2);
282 TEST_ASSERT_VAL("Unmatched total period for socket filter",
283 hists
->stats
.total_non_filtered_period
== 200);
285 /* remove socket filter first */
286 hists
->socket_filter
= -1;
287 hists__filter_by_socket(hists
);
289 /* now applying all filters at once. */
290 hists
->thread_filter
= fake_samples
[1].thread
;
291 hists
->dso_filter
= fake_samples
[1].map
->dso
;
292 hists__filter_by_thread(hists
);
293 hists__filter_by_dso(hists
);
296 pr_info("Histogram for all filters\n");
297 print_hists_out(hists
);
300 /* normal stats should be invariant */
301 TEST_ASSERT_VAL("Invalid nr samples",
302 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
303 TEST_ASSERT_VAL("Invalid nr hist entries",
304 hists
->nr_entries
== 9);
305 TEST_ASSERT_VAL("Invalid total period",
306 hists
->stats
.total_period
== 1000);
308 /* but filter stats are changed */
309 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
310 hists
->stats
.nr_non_filtered_samples
== 2);
311 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
312 hists
->nr_non_filtered_entries
== 1);
313 TEST_ASSERT_VAL("Unmatched total period for all filter",
314 hists
->stats
.total_non_filtered_period
== 200);
321 /* tear down everything */
322 perf_evlist__delete(evlist
);
323 reset_output_field();
324 machines__exit(&machines
);