2 #include "util/debug.h"
3 #include "util/symbol.h"
5 #include "util/evsel.h"
6 #include "util/evlist.h"
7 #include "util/machine.h"
8 #include "util/thread.h"
9 #include "util/parse-events.h"
10 #include "tests/tests.h"
11 #include "tests/hists_common.h"
12 #include <linux/kernel.h>
17 struct thread
*thread
;
23 /* For the numbers, see hists_common.c */
24 static struct sample fake_samples
[] = {
25 /* perf [kernel] schedule() */
26 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_KERNEL_SCHEDULE
, .socket
= 0 },
27 /* perf [perf] main() */
28 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_PERF_MAIN
, .socket
= 0 },
29 /* perf [libc] malloc() */
30 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_LIBC_MALLOC
, .socket
= 0 },
31 /* perf [perf] main() */
32 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_PERF_MAIN
, .socket
= 0 }, /* will be merged */
33 /* perf [perf] cmd_record() */
34 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_PERF_CMD_RECORD
, .socket
= 1 },
35 /* perf [kernel] page_fault() */
36 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_KERNEL_PAGE_FAULT
, .socket
= 1 },
37 /* bash [bash] main() */
38 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_BASH_MAIN
, .socket
= 2 },
39 /* bash [bash] xmalloc() */
40 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_BASH_XMALLOC
, .socket
= 2 },
41 /* bash [libc] malloc() */
42 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_LIBC_MALLOC
, .socket
= 3 },
43 /* bash [kernel] page_fault() */
44 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_KERNEL_PAGE_FAULT
, .socket
= 3 },
47 static int add_hist_entries(struct perf_evlist
*evlist
,
48 struct machine
*machine
)
50 struct perf_evsel
*evsel
;
51 struct addr_location al
;
52 struct perf_sample sample
= { .period
= 100, };
56 * each evsel will have 10 samples but the 4th sample
57 * (perf [perf] main) will be collapsed to an existing entry
58 * so total 9 entries will be in the tree.
60 evlist__for_each_entry(evlist
, evsel
) {
61 for (i
= 0; i
< ARRAY_SIZE(fake_samples
); i
++) {
62 struct hist_entry_iter iter
= {
65 .ops
= &hist_iter_normal
,
66 .hide_unresolved
= false,
68 struct hists
*hists
= evsel__hists(evsel
);
70 /* make sure it has no filter at first */
71 hists
->thread_filter
= NULL
;
72 hists
->dso_filter
= NULL
;
73 hists
->symbol_filter_str
= NULL
;
75 sample
.cpumode
= PERF_RECORD_MISC_USER
;
76 sample
.pid
= fake_samples
[i
].pid
;
77 sample
.tid
= fake_samples
[i
].pid
;
78 sample
.ip
= fake_samples
[i
].ip
;
80 if (machine__resolve(machine
, &al
, &sample
) < 0)
83 al
.socket
= fake_samples
[i
].socket
;
84 if (hist_entry_iter__add(&iter
, &al
,
85 sysctl_perf_event_max_stack
, NULL
) < 0) {
86 addr_location__put(&al
);
90 fake_samples
[i
].thread
= al
.thread
;
91 fake_samples
[i
].map
= al
.map
;
92 fake_samples
[i
].sym
= al
.sym
;
99 pr_debug("Not enough memory for adding a hist entry\n");
103 int test__hists_filter(int subtest __maybe_unused
)
106 struct machines machines
;
107 struct machine
*machine
;
108 struct perf_evsel
*evsel
;
109 struct perf_evlist
*evlist
= perf_evlist__new();
111 TEST_ASSERT_VAL("No memory", evlist
);
113 err
= parse_events(evlist
, "cpu-clock", NULL
);
116 err
= parse_events(evlist
, "task-clock", NULL
);
121 /* default sort order (comm,dso,sym) will be used */
122 if (setup_sorting(NULL
) < 0)
125 machines__init(&machines
);
127 /* setup threads/dso/map/symbols also */
128 machine
= setup_fake_machine(&machines
);
133 machine__fprintf(machine
, stderr
);
135 /* process sample events */
136 err
= add_hist_entries(evlist
, machine
);
140 evlist__for_each_entry(evlist
, evsel
) {
141 struct hists
*hists
= evsel__hists(evsel
);
143 hists__collapse_resort(hists
, NULL
);
144 perf_evsel__output_resort(evsel
, NULL
);
147 pr_info("Normal histogram\n");
148 print_hists_out(hists
);
151 TEST_ASSERT_VAL("Invalid nr samples",
152 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
153 TEST_ASSERT_VAL("Invalid nr hist entries",
154 hists
->nr_entries
== 9);
155 TEST_ASSERT_VAL("Invalid total period",
156 hists
->stats
.total_period
== 1000);
157 TEST_ASSERT_VAL("Unmatched nr samples",
158 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] ==
159 hists
->stats
.nr_non_filtered_samples
);
160 TEST_ASSERT_VAL("Unmatched nr hist entries",
161 hists
->nr_entries
== hists
->nr_non_filtered_entries
);
162 TEST_ASSERT_VAL("Unmatched total period",
163 hists
->stats
.total_period
==
164 hists
->stats
.total_non_filtered_period
);
166 /* now applying thread filter for 'bash' */
167 hists
->thread_filter
= fake_samples
[9].thread
;
168 hists__filter_by_thread(hists
);
171 pr_info("Histogram for thread filter\n");
172 print_hists_out(hists
);
175 /* normal stats should be invariant */
176 TEST_ASSERT_VAL("Invalid nr samples",
177 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
178 TEST_ASSERT_VAL("Invalid nr hist entries",
179 hists
->nr_entries
== 9);
180 TEST_ASSERT_VAL("Invalid total period",
181 hists
->stats
.total_period
== 1000);
183 /* but filter stats are changed */
184 TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
185 hists
->stats
.nr_non_filtered_samples
== 4);
186 TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
187 hists
->nr_non_filtered_entries
== 4);
188 TEST_ASSERT_VAL("Unmatched total period for thread filter",
189 hists
->stats
.total_non_filtered_period
== 400);
191 /* remove thread filter first */
192 hists
->thread_filter
= NULL
;
193 hists__filter_by_thread(hists
);
195 /* now applying dso filter for 'kernel' */
196 hists
->dso_filter
= fake_samples
[0].map
->dso
;
197 hists__filter_by_dso(hists
);
200 pr_info("Histogram for dso filter\n");
201 print_hists_out(hists
);
204 /* normal stats should be invariant */
205 TEST_ASSERT_VAL("Invalid nr samples",
206 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
207 TEST_ASSERT_VAL("Invalid nr hist entries",
208 hists
->nr_entries
== 9);
209 TEST_ASSERT_VAL("Invalid total period",
210 hists
->stats
.total_period
== 1000);
212 /* but filter stats are changed */
213 TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
214 hists
->stats
.nr_non_filtered_samples
== 3);
215 TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
216 hists
->nr_non_filtered_entries
== 3);
217 TEST_ASSERT_VAL("Unmatched total period for dso filter",
218 hists
->stats
.total_non_filtered_period
== 300);
220 /* remove dso filter first */
221 hists
->dso_filter
= NULL
;
222 hists__filter_by_dso(hists
);
225 * now applying symbol filter for 'main'. Also note that
226 * there's 3 samples that have 'main' symbol but the 4th
227 * entry of fake_samples was collapsed already so it won't
228 * be counted as a separate entry but the sample count and
229 * total period will be remained.
231 hists
->symbol_filter_str
= "main";
232 hists__filter_by_symbol(hists
);
235 pr_info("Histogram for symbol filter\n");
236 print_hists_out(hists
);
239 /* normal stats should be invariant */
240 TEST_ASSERT_VAL("Invalid nr samples",
241 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
242 TEST_ASSERT_VAL("Invalid nr hist entries",
243 hists
->nr_entries
== 9);
244 TEST_ASSERT_VAL("Invalid total period",
245 hists
->stats
.total_period
== 1000);
247 /* but filter stats are changed */
248 TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
249 hists
->stats
.nr_non_filtered_samples
== 3);
250 TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
251 hists
->nr_non_filtered_entries
== 2);
252 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
253 hists
->stats
.total_non_filtered_period
== 300);
255 /* remove symbol filter first */
256 hists
->symbol_filter_str
= NULL
;
257 hists__filter_by_symbol(hists
);
259 /* now applying socket filters */
260 hists
->socket_filter
= 2;
261 hists__filter_by_socket(hists
);
264 pr_info("Histogram for socket filters\n");
265 print_hists_out(hists
);
268 /* normal stats should be invariant */
269 TEST_ASSERT_VAL("Invalid nr samples",
270 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
271 TEST_ASSERT_VAL("Invalid nr hist entries",
272 hists
->nr_entries
== 9);
273 TEST_ASSERT_VAL("Invalid total period",
274 hists
->stats
.total_period
== 1000);
276 /* but filter stats are changed */
277 TEST_ASSERT_VAL("Unmatched nr samples for socket filter",
278 hists
->stats
.nr_non_filtered_samples
== 2);
279 TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter",
280 hists
->nr_non_filtered_entries
== 2);
281 TEST_ASSERT_VAL("Unmatched total period for socket filter",
282 hists
->stats
.total_non_filtered_period
== 200);
284 /* remove socket filter first */
285 hists
->socket_filter
= -1;
286 hists__filter_by_socket(hists
);
288 /* now applying all filters at once. */
289 hists
->thread_filter
= fake_samples
[1].thread
;
290 hists
->dso_filter
= fake_samples
[1].map
->dso
;
291 hists__filter_by_thread(hists
);
292 hists__filter_by_dso(hists
);
295 pr_info("Histogram for all filters\n");
296 print_hists_out(hists
);
299 /* normal stats should be invariant */
300 TEST_ASSERT_VAL("Invalid nr samples",
301 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
302 TEST_ASSERT_VAL("Invalid nr hist entries",
303 hists
->nr_entries
== 9);
304 TEST_ASSERT_VAL("Invalid total period",
305 hists
->stats
.total_period
== 1000);
307 /* but filter stats are changed */
308 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
309 hists
->stats
.nr_non_filtered_samples
== 2);
310 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
311 hists
->nr_non_filtered_entries
== 1);
312 TEST_ASSERT_VAL("Unmatched total period for all filter",
313 hists
->stats
.total_non_filtered_period
== 200);
320 /* tear down everything */
321 perf_evlist__delete(evlist
);
322 reset_output_field();
323 machines__exit(&machines
);