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
;
21 /* For the numbers, see hists_common.c */
22 static struct sample fake_samples
[] = {
23 /* perf [kernel] schedule() */
24 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_KERNEL_SCHEDULE
, },
25 /* perf [perf] main() */
26 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_PERF_MAIN
, },
27 /* perf [libc] malloc() */
28 { .pid
= FAKE_PID_PERF1
, .ip
= FAKE_IP_LIBC_MALLOC
, },
29 /* perf [perf] main() */
30 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_PERF_MAIN
, }, /* will be merged */
31 /* perf [perf] cmd_record() */
32 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_PERF_CMD_RECORD
, },
33 /* perf [kernel] page_fault() */
34 { .pid
= FAKE_PID_PERF2
, .ip
= FAKE_IP_KERNEL_PAGE_FAULT
, },
35 /* bash [bash] main() */
36 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_BASH_MAIN
, },
37 /* bash [bash] xmalloc() */
38 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_BASH_XMALLOC
, },
39 /* bash [libc] malloc() */
40 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_LIBC_MALLOC
, },
41 /* bash [kernel] page_fault() */
42 { .pid
= FAKE_PID_BASH
, .ip
= FAKE_IP_KERNEL_PAGE_FAULT
, },
45 static int add_hist_entries(struct perf_evlist
*evlist
,
46 struct machine
*machine __maybe_unused
)
48 struct perf_evsel
*evsel
;
49 struct addr_location al
;
50 struct perf_sample sample
= { .period
= 100, };
54 * each evsel will have 10 samples but the 4th sample
55 * (perf [perf] main) will be collapsed to an existing entry
56 * so total 9 entries will be in the tree.
58 evlist__for_each(evlist
, evsel
) {
59 for (i
= 0; i
< ARRAY_SIZE(fake_samples
); i
++) {
60 const union perf_event event
= {
62 .misc
= PERF_RECORD_MISC_USER
,
65 struct hist_entry_iter iter
= {
66 .ops
= &hist_iter_normal
,
67 .hide_unresolved
= false,
70 /* make sure it has no filter at first */
71 evsel
->hists
.thread_filter
= NULL
;
72 evsel
->hists
.dso_filter
= NULL
;
73 evsel
->hists
.symbol_filter_str
= NULL
;
75 sample
.pid
= fake_samples
[i
].pid
;
76 sample
.tid
= fake_samples
[i
].pid
;
77 sample
.ip
= fake_samples
[i
].ip
;
79 if (perf_event__preprocess_sample(&event
, machine
, &al
,
83 if (hist_entry_iter__add(&iter
, &al
, evsel
, &sample
,
84 PERF_MAX_STACK_DEPTH
, NULL
) < 0)
87 fake_samples
[i
].thread
= al
.thread
;
88 fake_samples
[i
].map
= al
.map
;
89 fake_samples
[i
].sym
= al
.sym
;
96 pr_debug("Not enough memory for adding a hist entry\n");
100 int test__hists_filter(void)
103 struct machines machines
;
104 struct machine
*machine
;
105 struct perf_evsel
*evsel
;
106 struct perf_evlist
*evlist
= perf_evlist__new();
108 TEST_ASSERT_VAL("No memory", evlist
);
110 err
= parse_events(evlist
, "cpu-clock");
113 err
= parse_events(evlist
, "task-clock");
117 /* default sort order (comm,dso,sym) will be used */
118 if (setup_sorting() < 0)
121 machines__init(&machines
);
123 /* setup threads/dso/map/symbols also */
124 machine
= setup_fake_machine(&machines
);
129 machine__fprintf(machine
, stderr
);
131 /* process sample events */
132 err
= add_hist_entries(evlist
, machine
);
136 evlist__for_each(evlist
, evsel
) {
137 struct hists
*hists
= &evsel
->hists
;
139 hists__collapse_resort(hists
, NULL
);
140 hists__output_resort(hists
);
143 pr_info("Normal histogram\n");
144 print_hists_out(hists
);
147 TEST_ASSERT_VAL("Invalid nr samples",
148 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
149 TEST_ASSERT_VAL("Invalid nr hist entries",
150 hists
->nr_entries
== 9);
151 TEST_ASSERT_VAL("Invalid total period",
152 hists
->stats
.total_period
== 1000);
153 TEST_ASSERT_VAL("Unmatched nr samples",
154 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] ==
155 hists
->stats
.nr_non_filtered_samples
);
156 TEST_ASSERT_VAL("Unmatched nr hist entries",
157 hists
->nr_entries
== hists
->nr_non_filtered_entries
);
158 TEST_ASSERT_VAL("Unmatched total period",
159 hists
->stats
.total_period
==
160 hists
->stats
.total_non_filtered_period
);
162 /* now applying thread filter for 'bash' */
163 evsel
->hists
.thread_filter
= fake_samples
[9].thread
;
164 hists__filter_by_thread(hists
);
167 pr_info("Histogram for thread filter\n");
168 print_hists_out(hists
);
171 /* normal stats should be invariant */
172 TEST_ASSERT_VAL("Invalid nr samples",
173 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
174 TEST_ASSERT_VAL("Invalid nr hist entries",
175 hists
->nr_entries
== 9);
176 TEST_ASSERT_VAL("Invalid total period",
177 hists
->stats
.total_period
== 1000);
179 /* but filter stats are changed */
180 TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
181 hists
->stats
.nr_non_filtered_samples
== 4);
182 TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
183 hists
->nr_non_filtered_entries
== 4);
184 TEST_ASSERT_VAL("Unmatched total period for thread filter",
185 hists
->stats
.total_non_filtered_period
== 400);
187 /* remove thread filter first */
188 evsel
->hists
.thread_filter
= NULL
;
189 hists__filter_by_thread(hists
);
191 /* now applying dso filter for 'kernel' */
192 evsel
->hists
.dso_filter
= fake_samples
[0].map
->dso
;
193 hists__filter_by_dso(hists
);
196 pr_info("Histogram for dso filter\n");
197 print_hists_out(hists
);
200 /* normal stats should be invariant */
201 TEST_ASSERT_VAL("Invalid nr samples",
202 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
203 TEST_ASSERT_VAL("Invalid nr hist entries",
204 hists
->nr_entries
== 9);
205 TEST_ASSERT_VAL("Invalid total period",
206 hists
->stats
.total_period
== 1000);
208 /* but filter stats are changed */
209 TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
210 hists
->stats
.nr_non_filtered_samples
== 3);
211 TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
212 hists
->nr_non_filtered_entries
== 3);
213 TEST_ASSERT_VAL("Unmatched total period for dso filter",
214 hists
->stats
.total_non_filtered_period
== 300);
216 /* remove dso filter first */
217 evsel
->hists
.dso_filter
= NULL
;
218 hists__filter_by_dso(hists
);
221 * now applying symbol filter for 'main'. Also note that
222 * there's 3 samples that have 'main' symbol but the 4th
223 * entry of fake_samples was collapsed already so it won't
224 * be counted as a separate entry but the sample count and
225 * total period will be remained.
227 evsel
->hists
.symbol_filter_str
= "main";
228 hists__filter_by_symbol(hists
);
231 pr_info("Histogram for symbol filter\n");
232 print_hists_out(hists
);
235 /* normal stats should be invariant */
236 TEST_ASSERT_VAL("Invalid nr samples",
237 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
238 TEST_ASSERT_VAL("Invalid nr hist entries",
239 hists
->nr_entries
== 9);
240 TEST_ASSERT_VAL("Invalid total period",
241 hists
->stats
.total_period
== 1000);
243 /* but filter stats are changed */
244 TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
245 hists
->stats
.nr_non_filtered_samples
== 3);
246 TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
247 hists
->nr_non_filtered_entries
== 2);
248 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
249 hists
->stats
.total_non_filtered_period
== 300);
251 /* now applying all filters at once. */
252 evsel
->hists
.thread_filter
= fake_samples
[1].thread
;
253 evsel
->hists
.dso_filter
= fake_samples
[1].map
->dso
;
254 hists__filter_by_thread(hists
);
255 hists__filter_by_dso(hists
);
258 pr_info("Histogram for all filters\n");
259 print_hists_out(hists
);
262 /* normal stats should be invariant */
263 TEST_ASSERT_VAL("Invalid nr samples",
264 hists
->stats
.nr_events
[PERF_RECORD_SAMPLE
] == 10);
265 TEST_ASSERT_VAL("Invalid nr hist entries",
266 hists
->nr_entries
== 9);
267 TEST_ASSERT_VAL("Invalid total period",
268 hists
->stats
.total_period
== 1000);
270 /* but filter stats are changed */
271 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
272 hists
->stats
.nr_non_filtered_samples
== 2);
273 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
274 hists
->nr_non_filtered_entries
== 1);
275 TEST_ASSERT_VAL("Unmatched total period for all filter",
276 hists
->stats
.total_non_filtered_period
== 200);
283 /* tear down everything */
284 perf_evlist__delete(evlist
);
285 reset_output_field();
286 machines__exit(&machines
);