]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - tools/perf/tests/hists_filter.c
Merge branch 'for-linus-4.12' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
[karo-tx-linux.git] / tools / perf / tests / hists_filter.c
1 #include "perf.h"
2 #include "util/debug.h"
3 #include "util/symbol.h"
4 #include "util/sort.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>
13
14 struct sample {
15         u32 pid;
16         u64 ip;
17         struct thread *thread;
18         struct map *map;
19         struct symbol *sym;
20         int socket;
21 };
22
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 },
45 };
46
47 static int add_hist_entries(struct perf_evlist *evlist,
48                             struct machine *machine)
49 {
50         struct perf_evsel *evsel;
51         struct addr_location al;
52         struct perf_sample sample = { .period = 100, };
53         size_t i;
54
55         /*
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.
59          */
60         evlist__for_each_entry(evlist, evsel) {
61                 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
62                         struct hist_entry_iter iter = {
63                                 .evsel = evsel,
64                                 .sample = &sample,
65                                 .ops = &hist_iter_normal,
66                                 .hide_unresolved = false,
67                         };
68                         struct hists *hists = evsel__hists(evsel);
69
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;
74
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;
79
80                         if (machine__resolve(machine, &al, &sample) < 0)
81                                 goto out;
82
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);
87                                 goto out;
88                         }
89
90                         fake_samples[i].thread = al.thread;
91                         fake_samples[i].map = al.map;
92                         fake_samples[i].sym = al.sym;
93                 }
94         }
95
96         return 0;
97
98 out:
99         pr_debug("Not enough memory for adding a hist entry\n");
100         return TEST_FAIL;
101 }
102
103 int test__hists_filter(int subtest __maybe_unused)
104 {
105         int err = TEST_FAIL;
106         struct machines machines;
107         struct machine *machine;
108         struct perf_evsel *evsel;
109         struct perf_evlist *evlist = perf_evlist__new();
110
111         TEST_ASSERT_VAL("No memory", evlist);
112
113         err = parse_events(evlist, "cpu-clock", NULL);
114         if (err)
115                 goto out;
116         err = parse_events(evlist, "task-clock", NULL);
117         if (err)
118                 goto out;
119         err = TEST_FAIL;
120
121         /* default sort order (comm,dso,sym) will be used */
122         if (setup_sorting(NULL) < 0)
123                 goto out;
124
125         machines__init(&machines);
126
127         /* setup threads/dso/map/symbols also */
128         machine = setup_fake_machine(&machines);
129         if (!machine)
130                 goto out;
131
132         if (verbose > 1)
133                 machine__fprintf(machine, stderr);
134
135         /* process sample events */
136         err = add_hist_entries(evlist, machine);
137         if (err < 0)
138                 goto out;
139
140         evlist__for_each_entry(evlist, evsel) {
141                 struct hists *hists = evsel__hists(evsel);
142
143                 hists__collapse_resort(hists, NULL);
144                 perf_evsel__output_resort(evsel, NULL);
145
146                 if (verbose > 2) {
147                         pr_info("Normal histogram\n");
148                         print_hists_out(hists);
149                 }
150
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);
165
166                 /* now applying thread filter for 'bash' */
167                 hists->thread_filter = fake_samples[9].thread;
168                 hists__filter_by_thread(hists);
169
170                 if (verbose > 2) {
171                         pr_info("Histogram for thread filter\n");
172                         print_hists_out(hists);
173                 }
174
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);
182
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);
190
191                 /* remove thread filter first */
192                 hists->thread_filter = NULL;
193                 hists__filter_by_thread(hists);
194
195                 /* now applying dso filter for 'kernel' */
196                 hists->dso_filter = fake_samples[0].map->dso;
197                 hists__filter_by_dso(hists);
198
199                 if (verbose > 2) {
200                         pr_info("Histogram for dso filter\n");
201                         print_hists_out(hists);
202                 }
203
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);
211
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);
219
220                 /* remove dso filter first */
221                 hists->dso_filter = NULL;
222                 hists__filter_by_dso(hists);
223
224                 /*
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.
230                  */
231                 hists->symbol_filter_str = "main";
232                 hists__filter_by_symbol(hists);
233
234                 if (verbose > 2) {
235                         pr_info("Histogram for symbol filter\n");
236                         print_hists_out(hists);
237                 }
238
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);
246
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);
254
255                 /* remove symbol filter first */
256                 hists->symbol_filter_str = NULL;
257                 hists__filter_by_symbol(hists);
258
259                 /* now applying socket filters */
260                 hists->socket_filter = 2;
261                 hists__filter_by_socket(hists);
262
263                 if (verbose > 2) {
264                         pr_info("Histogram for socket filters\n");
265                         print_hists_out(hists);
266                 }
267
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);
275
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);
283
284                 /* remove socket filter first */
285                 hists->socket_filter = -1;
286                 hists__filter_by_socket(hists);
287
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);
293
294                 if (verbose > 2) {
295                         pr_info("Histogram for all filters\n");
296                         print_hists_out(hists);
297                 }
298
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);
306
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);
314         }
315
316
317         err = TEST_OK;
318
319 out:
320         /* tear down everything */
321         perf_evlist__delete(evlist);
322         reset_output_field();
323         machines__exit(&machines);
324
325         return err;
326 }