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"
16 struct thread
*thread
;
22 /* For the numbers, see hists_common.c */
23 static struct sample fake_samples
[] = {
24 /* perf [kernel] schedule() */
25 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_KERNEL_SCHEDULE
, .socket
= 0 },
26 /* perf [perf] main() */
27 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_PERF_MAIN
, .socket
= 0 },
28 /* perf [libc] malloc() */
29 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_LIBC_MALLOC
, .socket
= 0 },
30 /* perf [perf] main() */
31 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_PERF_MAIN
, .socket
= 0 }, /* will be merged */
32 /* perf [perf] cmd_record() */
33 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_PERF_CMD_RECORD
, .socket
= 1 },
34 /* perf [kernel] page_fault() */
35 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_KERNEL_PAGE_FAULT
, .socket
= 1 },
36 /* bash [bash] main() */
37 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_BASH_MAIN
, .socket
= 2 },
38 /* bash [bash] xmalloc() */
39 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_BASH_XMALLOC
, .socket
= 2 },
40 /* bash [libc] malloc() */
41 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_LIBC_MALLOC
, .socket
= 3 },
42 /* bash [kernel] page_fault() */
43 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_KERNEL_PAGE_FAULT
, .socket
= 3 },
46 static int add_hist_entries(struct perf_evlist
*evlist
,
47 struct machine
*machine
)
49 struct perf_evsel
*evsel
;
50 struct addr_location al
;
51 struct perf_sample sample
= { .period
= 100, };
55 * each evsel will have 10 samples but the 4th sample
56 * (perf [perf] main) will be collapsed to an existing entry
57 * so total 9 entries will be in the tree.
59 evlist__for_each(evlist
, evsel
) {
60 for (i
= 0; i
< ARRAY_SIZE(fake_samples
); i
++) {
61 const union perf_event event
= {
63 .misc
= PERF_RECORD_MISC_USER
,
66 struct hist_entry_iter iter
= {
69 .ops
= &hist_iter_normal
,
70 .hide_unresolved
= false,
72 struct hists
*hists
= evsel__hists(evsel
);
74 /* make sure it has no filter at first */
75 hists
->thread_filter
= NULL
;
76 hists
->dso_filter
= NULL
;
77 hists
->symbol_filter_str
= NULL
;
79 sample
.pid
= fake_samples
[i
].pid
;
80 sample
.tid
= fake_samples
[i
].pid
;
81 sample
.ip
= fake_samples
[i
].ip
;
83 if (perf_event__preprocess_sample(&event
, machine
, &al
,
87 al
.socket
= fake_samples
[i
].socket
;
88 if (hist_entry_iter__add(&iter
, &al
,
89 PERF_MAX_STACK_DEPTH
, NULL
) < 0) {
90 addr_location__put(&al
);
94 fake_samples
[i
].thread
= al
.thread
;
95 fake_samples
[i
].map
= al
.map
;
96 fake_samples
[i
].sym
= al
.sym
;
103 pr_debug("Not enough memory for adding a hist entry\n");
107 int test__hists_filter(int subtest __maybe_unused
)
110 struct machines machines
;
111 struct machine
*machine
;
112 struct perf_evsel
*evsel
;
113 struct perf_evlist
*evlist
= perf_evlist__new();
115 TEST_ASSERT_VAL("No memory", evlist
);
117 err
= parse_events(evlist
, "cpu-clock", NULL
);
120 err
= parse_events(evlist
, "task-clock", NULL
);
125 /* default sort order (comm,dso,sym) will be used */
126 if (setup_sorting(NULL
) < 0)
129 machines__init(&machines
);
131 /* setup threads/dso/map/symbols also */
132 machine
= setup_fake_machine(&machines
);
137 machine__fprintf(machine
, stderr
);
139 /* process sample events */
140 err
= add_hist_entries(evlist
, machine
);
144 evlist__for_each(evlist
, evsel
) {
145 struct hists
*hists
= evsel__hists(evsel
);
147 hists__collapse_resort(hists
, NULL
);
148 hists__output_resort(hists
, NULL
);
151 pr_info("Normal histogram\n");
152 print_hists_out(hists
);
155 TEST_ASSERT_VAL("Invalid nr samples",
156 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
157 TEST_ASSERT_VAL("Invalid nr hist entries",
158 hists
->nr_entries
== 9);
159 TEST_ASSERT_VAL("Invalid total period",
160 hists
->stats
.total_period
== 1000);
161 TEST_ASSERT_VAL("Unmatched nr samples",
162 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] ==
163 hists
->stats
.nr_non_filtered_samples
);
164 TEST_ASSERT_VAL("Unmatched nr hist entries",
165 hists
->nr_entries
== hists
->nr_non_filtered_entries
);
166 TEST_ASSERT_VAL("Unmatched total period",
167 hists
->stats
.total_period
==
168 hists
->stats
.total_non_filtered_period
);
170 /* now applying thread filter for 'bash' */
171 hists
->thread_filter
= fake_samples
[9].thread
;
172 hists__filter_by_thread(hists
);
175 pr_info("Histogram for thread filter\n");
176 print_hists_out(hists
);
179 /* normal stats should be invariant */
180 TEST_ASSERT_VAL("Invalid nr samples",
181 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
182 TEST_ASSERT_VAL("Invalid nr hist entries",
183 hists
->nr_entries
== 9);
184 TEST_ASSERT_VAL("Invalid total period",
185 hists
->stats
.total_period
== 1000);
187 /* but filter stats are changed */
188 TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
189 hists
->stats
.nr_non_filtered_samples
== 4);
190 TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
191 hists
->nr_non_filtered_entries
== 4);
192 TEST_ASSERT_VAL("Unmatched total period for thread filter",
193 hists
->stats
.total_non_filtered_period
== 400);
195 /* remove thread filter first */
196 hists
->thread_filter
= NULL
;
197 hists__filter_by_thread(hists
);
199 /* now applying dso filter for 'kernel' */
200 hists
->dso_filter
= fake_samples
[0].map
->dso
;
201 hists__filter_by_dso(hists
);
204 pr_info("Histogram for dso filter\n");
205 print_hists_out(hists
);
208 /* normal stats should be invariant */
209 TEST_ASSERT_VAL("Invalid nr samples",
210 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
211 TEST_ASSERT_VAL("Invalid nr hist entries",
212 hists
->nr_entries
== 9);
213 TEST_ASSERT_VAL("Invalid total period",
214 hists
->stats
.total_period
== 1000);
216 /* but filter stats are changed */
217 TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
218 hists
->stats
.nr_non_filtered_samples
== 3);
219 TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
220 hists
->nr_non_filtered_entries
== 3);
221 TEST_ASSERT_VAL("Unmatched total period for dso filter",
222 hists
->stats
.total_non_filtered_period
== 300);
224 /* remove dso filter first */
225 hists
->dso_filter
= NULL
;
226 hists__filter_by_dso(hists
);
229 * now applying symbol filter for 'main'. Also note that
230 * there's 3 samples that have 'main' symbol but the 4th
231 * entry of fake_samples was collapsed already so it won't
232 * be counted as a separate entry but the sample count and
233 * total period will be remained.
235 hists
->symbol_filter_str
= "main";
236 hists__filter_by_symbol(hists
);
239 pr_info("Histogram for symbol filter\n");
240 print_hists_out(hists
);
243 /* normal stats should be invariant */
244 TEST_ASSERT_VAL("Invalid nr samples",
245 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
246 TEST_ASSERT_VAL("Invalid nr hist entries",
247 hists
->nr_entries
== 9);
248 TEST_ASSERT_VAL("Invalid total period",
249 hists
->stats
.total_period
== 1000);
251 /* but filter stats are changed */
252 TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
253 hists
->stats
.nr_non_filtered_samples
== 3);
254 TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
255 hists
->nr_non_filtered_entries
== 2);
256 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
257 hists
->stats
.total_non_filtered_period
== 300);
259 /* remove symbol filter first */
260 hists
->symbol_filter_str
= NULL
;
261 hists__filter_by_symbol(hists
);
263 /* now applying socket filters */
264 hists
->socket_filter
= 2;
265 hists__filter_by_socket(hists
);
268 pr_info("Histogram for socket filters\n");
269 print_hists_out(hists
);
272 /* normal stats should be invariant */
273 TEST_ASSERT_VAL("Invalid nr samples",
274 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
275 TEST_ASSERT_VAL("Invalid nr hist entries",
276 hists
->nr_entries
== 9);
277 TEST_ASSERT_VAL("Invalid total period",
278 hists
->stats
.total_period
== 1000);
280 /* but filter stats are changed */
281 TEST_ASSERT_VAL("Unmatched nr samples for socket filter",
282 hists
->stats
.nr_non_filtered_samples
== 2);
283 TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter",
284 hists
->nr_non_filtered_entries
== 2);
285 TEST_ASSERT_VAL("Unmatched total period for socket filter",
286 hists
->stats
.total_non_filtered_period
== 200);
288 /* remove socket filter first */
289 hists
->socket_filter
= -1;
290 hists__filter_by_socket(hists
);
292 /* now applying all filters at once. */
293 hists
->thread_filter
= fake_samples
[1].thread
;
294 hists
->dso_filter
= fake_samples
[1].map
->dso
;
295 hists__filter_by_thread(hists
);
296 hists__filter_by_dso(hists
);
299 pr_info("Histogram for all filters\n");
300 print_hists_out(hists
);
303 /* normal stats should be invariant */
304 TEST_ASSERT_VAL("Invalid nr samples",
305 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
306 TEST_ASSERT_VAL("Invalid nr hist entries",
307 hists
->nr_entries
== 9);
308 TEST_ASSERT_VAL("Invalid total period",
309 hists
->stats
.total_period
== 1000);
311 /* but filter stats are changed */
312 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
313 hists
->stats
.nr_non_filtered_samples
== 2);
314 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
315 hists
->nr_non_filtered_entries
== 1);
316 TEST_ASSERT_VAL("Unmatched total period for all filter",
317 hists
->stats
.total_non_filtered_period
== 200);
324 /* tear down everything */
325 perf_evlist__delete(evlist
);
326 reset_output_field();
327 machines__exit(&machines
);