License cleanup: add SPDX GPL-2.0 license identifier to files with no license
[linux-2.6-block.git] / tools / perf / tests / hists_filter.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
3c3cfd99
NK
2#include "perf.h"
3#include "util/debug.h"
4#include "util/symbol.h"
5#include "util/sort.h"
6#include "util/evsel.h"
5ab8c689 7#include "util/event.h"
3c3cfd99
NK
8#include "util/evlist.h"
9#include "util/machine.h"
10#include "util/thread.h"
11#include "util/parse-events.h"
12#include "tests/tests.h"
13#include "tests/hists_common.h"
877a7a11 14#include <linux/kernel.h>
3c3cfd99
NK
15
16struct sample {
17 u32 pid;
18 u64 ip;
19 struct thread *thread;
20 struct map *map;
21 struct symbol *sym;
92d424ae 22 int socket;
3c3cfd99
NK
23};
24
25/* For the numbers, see hists_common.c */
26static struct sample fake_samples[] = {
27 /* perf [kernel] schedule() */
92d424ae 28 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, .socket = 0 },
3c3cfd99 29 /* perf [perf] main() */
92d424ae 30 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, .socket = 0 },
3c3cfd99 31 /* perf [libc] malloc() */
92d424ae 32 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, .socket = 0 },
3c3cfd99 33 /* perf [perf] main() */
92d424ae 34 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, .socket = 0 }, /* will be merged */
3c3cfd99 35 /* perf [perf] cmd_record() */
92d424ae 36 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, .socket = 1 },
3c3cfd99 37 /* perf [kernel] page_fault() */
92d424ae 38 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 1 },
3c3cfd99 39 /* bash [bash] main() */
92d424ae 40 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, .socket = 2 },
3c3cfd99 41 /* bash [bash] xmalloc() */
92d424ae 42 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, .socket = 2 },
3c3cfd99 43 /* bash [libc] malloc() */
92d424ae 44 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_LIBC_MALLOC, .socket = 3 },
3c3cfd99 45 /* bash [kernel] page_fault() */
92d424ae 46 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 },
3c3cfd99
NK
47};
48
69bcb019 49static int add_hist_entries(struct perf_evlist *evlist,
f498784c 50 struct machine *machine)
3c3cfd99
NK
51{
52 struct perf_evsel *evsel;
53 struct addr_location al;
a1891aa4 54 struct perf_sample sample = { .period = 100, };
3c3cfd99
NK
55 size_t i;
56
57 /*
58 * each evsel will have 10 samples but the 4th sample
59 * (perf [perf] main) will be collapsed to an existing entry
60 * so total 9 entries will be in the tree.
61 */
e5cadb93 62 evlist__for_each_entry(evlist, evsel) {
3c3cfd99 63 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
69bcb019 64 struct hist_entry_iter iter = {
063bd936
NK
65 .evsel = evsel,
66 .sample = &sample,
69bcb019
NK
67 .ops = &hist_iter_normal,
68 .hide_unresolved = false,
69 };
4ea062ed 70 struct hists *hists = evsel__hists(evsel);
3c3cfd99
NK
71
72 /* make sure it has no filter at first */
4ea062ed
ACM
73 hists->thread_filter = NULL;
74 hists->dso_filter = NULL;
75 hists->symbol_filter_str = NULL;
3c3cfd99 76
473398a2 77 sample.cpumode = PERF_RECORD_MISC_USER;
3c3cfd99 78 sample.pid = fake_samples[i].pid;
13ce34df 79 sample.tid = fake_samples[i].pid;
3c3cfd99
NK
80 sample.ip = fake_samples[i].ip;
81
bb3eb566 82 if (machine__resolve(machine, &al, &sample) < 0)
3c3cfd99
NK
83 goto out;
84
92d424ae 85 al.socket = fake_samples[i].socket;
063bd936 86 if (hist_entry_iter__add(&iter, &al,
4cb93446 87 sysctl_perf_event_max_stack, NULL) < 0) {
b91fc39f 88 addr_location__put(&al);
3c3cfd99 89 goto out;
b91fc39f 90 }
3c3cfd99
NK
91
92 fake_samples[i].thread = al.thread;
93 fake_samples[i].map = al.map;
94 fake_samples[i].sym = al.sym;
3c3cfd99
NK
95 }
96 }
97
98 return 0;
99
100out:
101 pr_debug("Not enough memory for adding a hist entry\n");
102 return TEST_FAIL;
103}
104
81f17c90 105int test__hists_filter(struct test *test __maybe_unused, int subtest __maybe_unused)
3c3cfd99
NK
106{
107 int err = TEST_FAIL;
108 struct machines machines;
109 struct machine *machine;
110 struct perf_evsel *evsel;
111 struct perf_evlist *evlist = perf_evlist__new();
112
113 TEST_ASSERT_VAL("No memory", evlist);
114
b39b8393 115 err = parse_events(evlist, "cpu-clock", NULL);
3c3cfd99
NK
116 if (err)
117 goto out;
b39b8393 118 err = parse_events(evlist, "task-clock", NULL);
3c3cfd99
NK
119 if (err)
120 goto out;
b0500c16 121 err = TEST_FAIL;
3c3cfd99
NK
122
123 /* default sort order (comm,dso,sym) will be used */
40184c46 124 if (setup_sorting(NULL) < 0)
3c3cfd99
NK
125 goto out;
126
127 machines__init(&machines);
128
129 /* setup threads/dso/map/symbols also */
130 machine = setup_fake_machine(&machines);
131 if (!machine)
132 goto out;
133
134 if (verbose > 1)
135 machine__fprintf(machine, stderr);
136
137 /* process sample events */
138 err = add_hist_entries(evlist, machine);
139 if (err < 0)
140 goto out;
141
e5cadb93 142 evlist__for_each_entry(evlist, evsel) {
4ea062ed 143 struct hists *hists = evsel__hists(evsel);
3c3cfd99
NK
144
145 hists__collapse_resort(hists, NULL);
452ce03b 146 perf_evsel__output_resort(evsel, NULL);
3c3cfd99
NK
147
148 if (verbose > 2) {
149 pr_info("Normal histogram\n");
4e754e1c 150 print_hists_out(hists);
3c3cfd99
NK
151 }
152
153 TEST_ASSERT_VAL("Invalid nr samples",
154 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
155 TEST_ASSERT_VAL("Invalid nr hist entries",
156 hists->nr_entries == 9);
157 TEST_ASSERT_VAL("Invalid total period",
158 hists->stats.total_period == 1000);
159 TEST_ASSERT_VAL("Unmatched nr samples",
160 hists->stats.nr_events[PERF_RECORD_SAMPLE] ==
161 hists->stats.nr_non_filtered_samples);
162 TEST_ASSERT_VAL("Unmatched nr hist entries",
163 hists->nr_entries == hists->nr_non_filtered_entries);
164 TEST_ASSERT_VAL("Unmatched total period",
165 hists->stats.total_period ==
166 hists->stats.total_non_filtered_period);
167
168 /* now applying thread filter for 'bash' */
4ea062ed 169 hists->thread_filter = fake_samples[9].thread;
3c3cfd99
NK
170 hists__filter_by_thread(hists);
171
172 if (verbose > 2) {
173 pr_info("Histogram for thread filter\n");
4e754e1c 174 print_hists_out(hists);
3c3cfd99
NK
175 }
176
177 /* normal stats should be invariant */
178 TEST_ASSERT_VAL("Invalid nr samples",
179 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
180 TEST_ASSERT_VAL("Invalid nr hist entries",
181 hists->nr_entries == 9);
182 TEST_ASSERT_VAL("Invalid total period",
183 hists->stats.total_period == 1000);
184
185 /* but filter stats are changed */
186 TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
187 hists->stats.nr_non_filtered_samples == 4);
188 TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
189 hists->nr_non_filtered_entries == 4);
190 TEST_ASSERT_VAL("Unmatched total period for thread filter",
191 hists->stats.total_non_filtered_period == 400);
192
193 /* remove thread filter first */
4ea062ed 194 hists->thread_filter = NULL;
3c3cfd99
NK
195 hists__filter_by_thread(hists);
196
197 /* now applying dso filter for 'kernel' */
4ea062ed 198 hists->dso_filter = fake_samples[0].map->dso;
3c3cfd99
NK
199 hists__filter_by_dso(hists);
200
201 if (verbose > 2) {
202 pr_info("Histogram for dso filter\n");
4e754e1c 203 print_hists_out(hists);
3c3cfd99
NK
204 }
205
206 /* normal stats should be invariant */
207 TEST_ASSERT_VAL("Invalid nr samples",
208 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
209 TEST_ASSERT_VAL("Invalid nr hist entries",
210 hists->nr_entries == 9);
211 TEST_ASSERT_VAL("Invalid total period",
212 hists->stats.total_period == 1000);
213
214 /* but filter stats are changed */
215 TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
216 hists->stats.nr_non_filtered_samples == 3);
217 TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
218 hists->nr_non_filtered_entries == 3);
219 TEST_ASSERT_VAL("Unmatched total period for dso filter",
220 hists->stats.total_non_filtered_period == 300);
221
222 /* remove dso filter first */
4ea062ed 223 hists->dso_filter = NULL;
3c3cfd99
NK
224 hists__filter_by_dso(hists);
225
226 /*
227 * now applying symbol filter for 'main'. Also note that
228 * there's 3 samples that have 'main' symbol but the 4th
229 * entry of fake_samples was collapsed already so it won't
230 * be counted as a separate entry but the sample count and
231 * total period will be remained.
232 */
4ea062ed 233 hists->symbol_filter_str = "main";
3c3cfd99
NK
234 hists__filter_by_symbol(hists);
235
236 if (verbose > 2) {
237 pr_info("Histogram for symbol filter\n");
4e754e1c 238 print_hists_out(hists);
3c3cfd99
NK
239 }
240
241 /* normal stats should be invariant */
242 TEST_ASSERT_VAL("Invalid nr samples",
243 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
244 TEST_ASSERT_VAL("Invalid nr hist entries",
245 hists->nr_entries == 9);
246 TEST_ASSERT_VAL("Invalid total period",
247 hists->stats.total_period == 1000);
248
249 /* but filter stats are changed */
250 TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
251 hists->stats.nr_non_filtered_samples == 3);
252 TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
253 hists->nr_non_filtered_entries == 2);
254 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
255 hists->stats.total_non_filtered_period == 300);
256
92d424ae
KL
257 /* remove symbol filter first */
258 hists->symbol_filter_str = NULL;
259 hists__filter_by_symbol(hists);
260
261 /* now applying socket filters */
262 hists->socket_filter = 2;
263 hists__filter_by_socket(hists);
264
265 if (verbose > 2) {
266 pr_info("Histogram for socket filters\n");
267 print_hists_out(hists);
268 }
269
270 /* normal stats should be invariant */
271 TEST_ASSERT_VAL("Invalid nr samples",
272 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
273 TEST_ASSERT_VAL("Invalid nr hist entries",
274 hists->nr_entries == 9);
275 TEST_ASSERT_VAL("Invalid total period",
276 hists->stats.total_period == 1000);
277
278 /* but filter stats are changed */
279 TEST_ASSERT_VAL("Unmatched nr samples for socket filter",
280 hists->stats.nr_non_filtered_samples == 2);
281 TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter",
282 hists->nr_non_filtered_entries == 2);
283 TEST_ASSERT_VAL("Unmatched total period for socket filter",
284 hists->stats.total_non_filtered_period == 200);
285
286 /* remove socket filter first */
287 hists->socket_filter = -1;
288 hists__filter_by_socket(hists);
289
3c3cfd99 290 /* now applying all filters at once. */
4ea062ed
ACM
291 hists->thread_filter = fake_samples[1].thread;
292 hists->dso_filter = fake_samples[1].map->dso;
3c3cfd99
NK
293 hists__filter_by_thread(hists);
294 hists__filter_by_dso(hists);
295
296 if (verbose > 2) {
297 pr_info("Histogram for all filters\n");
4e754e1c 298 print_hists_out(hists);
3c3cfd99
NK
299 }
300
301 /* normal stats should be invariant */
302 TEST_ASSERT_VAL("Invalid nr samples",
303 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
304 TEST_ASSERT_VAL("Invalid nr hist entries",
305 hists->nr_entries == 9);
306 TEST_ASSERT_VAL("Invalid total period",
307 hists->stats.total_period == 1000);
308
309 /* but filter stats are changed */
310 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
311 hists->stats.nr_non_filtered_samples == 2);
312 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
313 hists->nr_non_filtered_entries == 1);
314 TEST_ASSERT_VAL("Unmatched total period for all filter",
315 hists->stats.total_non_filtered_period == 200);
316 }
317
318
319 err = TEST_OK;
320
321out:
322 /* tear down everything */
323 perf_evlist__delete(evlist);
f21d1815 324 reset_output_field();
3c3cfd99
NK
325 machines__exit(&machines);
326
327 return err;
328}