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)
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 = {
68 .ops = &hist_iter_normal,
69 .hide_unresolved = false,
71 struct hists *hists = evsel__hists(evsel);
73 /* make sure it has no filter at first */
74 hists->thread_filter = NULL;
75 hists->dso_filter = NULL;
76 hists->symbol_filter_str = NULL;
78 sample.pid = fake_samples[i].pid;
79 sample.tid = fake_samples[i].pid;
80 sample.ip = fake_samples[i].ip;
82 if (perf_event__preprocess_sample(&event, machine, &al,
86 if (hist_entry_iter__add(&iter, &al,
87 PERF_MAX_STACK_DEPTH, NULL) < 0) {
88 addr_location__put(&al);
92 fake_samples[i].thread = al.thread;
93 fake_samples[i].map = al.map;
94 fake_samples[i].sym = al.sym;
101 pr_debug("Not enough memory for adding a hist entry\n");
105 int test__hists_filter(void)
108 struct machines machines;
109 struct machine *machine;
110 struct perf_evsel *evsel;
111 struct perf_evlist *evlist = perf_evlist__new();
113 TEST_ASSERT_VAL("No memory", evlist);
115 err = parse_events(evlist, "cpu-clock", NULL);
118 err = parse_events(evlist, "task-clock", NULL);
122 /* default sort order (comm,dso,sym) will be used */
123 if (setup_sorting() < 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(evlist, evsel) {
142 struct hists *hists = evsel__hists(evsel);
144 hists__collapse_resort(hists, NULL);
145 hists__output_resort(hists, 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 /* now applying all filters at once. */
257 hists->thread_filter = fake_samples[1].thread;
258 hists->dso_filter = fake_samples[1].map->dso;
259 hists__filter_by_thread(hists);
260 hists__filter_by_dso(hists);
263 pr_info("Histogram for all filters\n");
264 print_hists_out(hists);
267 /* normal stats should be invariant */
268 TEST_ASSERT_VAL("Invalid nr samples",
269 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
270 TEST_ASSERT_VAL("Invalid nr hist entries",
271 hists->nr_entries == 9);
272 TEST_ASSERT_VAL("Invalid total period",
273 hists->stats.total_period == 1000);
275 /* but filter stats are changed */
276 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
277 hists->stats.nr_non_filtered_samples == 2);
278 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
279 hists->nr_non_filtered_entries == 1);
280 TEST_ASSERT_VAL("Unmatched total period for all filter",
281 hists->stats.total_non_filtered_period == 200);
288 /* tear down everything */
289 perf_evlist__delete(evlist);
290 reset_output_field();
291 machines__exit(&machines);