Merge tag 'clk-for-linus-3.16-part2' of git://git.linaro.org/people/mike.turquette...
[sfrench/cifs-2.6.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
13 struct sample {
14         u32 pid;
15         u64 ip;
16         struct thread *thread;
17         struct map *map;
18         struct symbol *sym;
19 };
20
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, },
43 };
44
45 static int add_hist_entries(struct perf_evlist *evlist,
46                             struct machine *machine __maybe_unused)
47 {
48         struct perf_evsel *evsel;
49         struct addr_location al;
50         struct perf_sample sample = { .period = 100, };
51         size_t i;
52
53         /*
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.
57          */
58         evlist__for_each(evlist, evsel) {
59                 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
60                         const union perf_event event = {
61                                 .header = {
62                                         .misc = PERF_RECORD_MISC_USER,
63                                 },
64                         };
65                         struct hist_entry_iter iter = {
66                                 .ops = &hist_iter_normal,
67                                 .hide_unresolved = false,
68                         };
69
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;
74
75                         sample.pid = fake_samples[i].pid;
76                         sample.tid = fake_samples[i].pid;
77                         sample.ip = fake_samples[i].ip;
78
79                         if (perf_event__preprocess_sample(&event, machine, &al,
80                                                           &sample) < 0)
81                                 goto out;
82
83                         if (hist_entry_iter__add(&iter, &al, evsel, &sample,
84                                                  PERF_MAX_STACK_DEPTH, NULL) < 0)
85                                 goto out;
86
87                         fake_samples[i].thread = al.thread;
88                         fake_samples[i].map = al.map;
89                         fake_samples[i].sym = al.sym;
90                 }
91         }
92
93         return 0;
94
95 out:
96         pr_debug("Not enough memory for adding a hist entry\n");
97         return TEST_FAIL;
98 }
99
100 int test__hists_filter(void)
101 {
102         int err = TEST_FAIL;
103         struct machines machines;
104         struct machine *machine;
105         struct perf_evsel *evsel;
106         struct perf_evlist *evlist = perf_evlist__new();
107
108         TEST_ASSERT_VAL("No memory", evlist);
109
110         err = parse_events(evlist, "cpu-clock");
111         if (err)
112                 goto out;
113         err = parse_events(evlist, "task-clock");
114         if (err)
115                 goto out;
116
117         /* default sort order (comm,dso,sym) will be used */
118         if (setup_sorting() < 0)
119                 goto out;
120
121         machines__init(&machines);
122
123         /* setup threads/dso/map/symbols also */
124         machine = setup_fake_machine(&machines);
125         if (!machine)
126                 goto out;
127
128         if (verbose > 1)
129                 machine__fprintf(machine, stderr);
130
131         /* process sample events */
132         err = add_hist_entries(evlist, machine);
133         if (err < 0)
134                 goto out;
135
136         evlist__for_each(evlist, evsel) {
137                 struct hists *hists = &evsel->hists;
138
139                 hists__collapse_resort(hists, NULL);
140                 hists__output_resort(hists);
141
142                 if (verbose > 2) {
143                         pr_info("Normal histogram\n");
144                         print_hists_out(hists);
145                 }
146
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);
161
162                 /* now applying thread filter for 'bash' */
163                 evsel->hists.thread_filter = fake_samples[9].thread;
164                 hists__filter_by_thread(hists);
165
166                 if (verbose > 2) {
167                         pr_info("Histogram for thread filter\n");
168                         print_hists_out(hists);
169                 }
170
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);
178
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);
186
187                 /* remove thread filter first */
188                 evsel->hists.thread_filter = NULL;
189                 hists__filter_by_thread(hists);
190
191                 /* now applying dso filter for 'kernel' */
192                 evsel->hists.dso_filter = fake_samples[0].map->dso;
193                 hists__filter_by_dso(hists);
194
195                 if (verbose > 2) {
196                         pr_info("Histogram for dso filter\n");
197                         print_hists_out(hists);
198                 }
199
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);
207
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);
215
216                 /* remove dso filter first */
217                 evsel->hists.dso_filter = NULL;
218                 hists__filter_by_dso(hists);
219
220                 /*
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.
226                  */
227                 evsel->hists.symbol_filter_str = "main";
228                 hists__filter_by_symbol(hists);
229
230                 if (verbose > 2) {
231                         pr_info("Histogram for symbol filter\n");
232                         print_hists_out(hists);
233                 }
234
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);
242
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);
250
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);
256
257                 if (verbose > 2) {
258                         pr_info("Histogram for all filters\n");
259                         print_hists_out(hists);
260                 }
261
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);
269
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);
277         }
278
279
280         err = TEST_OK;
281
282 out:
283         /* tear down everything */
284         perf_evlist__delete(evlist);
285         reset_output_field();
286         machines__exit(&machines);
287
288         return err;
289 }