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 = 100, .ip = 0xf0000 + 700, },
25 /* perf [perf] main() */
26 { .pid = 100, .ip = 0x40000 + 700, },
27 /* perf [libc] malloc() */
28 { .pid = 100, .ip = 0x50000 + 700, },
29 /* perf [perf] main() */
30 { .pid = 200, .ip = 0x40000 + 700, }, /* will be merged */
31 /* perf [perf] cmd_record() */
32 { .pid = 200, .ip = 0x40000 + 900, },
33 /* perf [kernel] page_fault() */
34 { .pid = 200, .ip = 0xf0000 + 800, },
35 /* bash [bash] main() */
36 { .pid = 300, .ip = 0x40000 + 700, },
37 /* bash [bash] xmalloc() */
38 { .pid = 300, .ip = 0x40000 + 800, },
39 /* bash [libc] malloc() */
40 { .pid = 300, .ip = 0x50000 + 700, },
41 /* bash [kernel] page_fault() */
42 { .pid = 300, .ip = 0xf0000 + 800, },
45 static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
47 struct perf_evsel *evsel;
48 struct addr_location al;
49 struct hist_entry *he;
50 struct perf_sample sample = { .cpu = 0, };
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,
66 /* make sure it has no filter at first */
67 evsel->hists.thread_filter = NULL;
68 evsel->hists.dso_filter = NULL;
69 evsel->hists.symbol_filter_str = NULL;
71 sample.pid = fake_samples[i].pid;
72 sample.tid = fake_samples[i].pid;
73 sample.ip = fake_samples[i].ip;
75 if (perf_event__preprocess_sample(&event, machine, &al,
79 he = __hists__add_entry(&evsel->hists, &al, NULL,
80 NULL, NULL, 100, 1, 0);
84 fake_samples[i].thread = al.thread;
85 fake_samples[i].map = al.map;
86 fake_samples[i].sym = al.sym;
88 hists__inc_nr_events(he->hists, PERF_RECORD_SAMPLE);
90 he->hists->stats.nr_non_filtered_samples++;
97 pr_debug("Not enough memory for adding a hist entry\n");
101 int test__hists_filter(void)
104 struct machines machines;
105 struct machine *machine;
106 struct perf_evsel *evsel;
107 struct perf_evlist *evlist = perf_evlist__new();
109 TEST_ASSERT_VAL("No memory", evlist);
111 err = parse_events(evlist, "cpu-clock");
114 err = parse_events(evlist, "task-clock");
118 /* default sort order (comm,dso,sym) will be used */
119 if (setup_sorting() < 0)
122 machines__init(&machines);
124 /* setup threads/dso/map/symbols also */
125 machine = setup_fake_machine(&machines);
130 machine__fprintf(machine, stderr);
132 /* process sample events */
133 err = add_hist_entries(evlist, machine);
137 evlist__for_each(evlist, evsel) {
138 struct hists *hists = &evsel->hists;
140 hists__collapse_resort(hists, NULL);
141 hists__output_resort(hists);
144 pr_info("Normal histogram\n");
145 print_hists_out(hists);
148 TEST_ASSERT_VAL("Invalid nr samples",
149 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
150 TEST_ASSERT_VAL("Invalid nr hist entries",
151 hists->nr_entries == 9);
152 TEST_ASSERT_VAL("Invalid total period",
153 hists->stats.total_period == 1000);
154 TEST_ASSERT_VAL("Unmatched nr samples",
155 hists->stats.nr_events[PERF_RECORD_SAMPLE] ==
156 hists->stats.nr_non_filtered_samples);
157 TEST_ASSERT_VAL("Unmatched nr hist entries",
158 hists->nr_entries == hists->nr_non_filtered_entries);
159 TEST_ASSERT_VAL("Unmatched total period",
160 hists->stats.total_period ==
161 hists->stats.total_non_filtered_period);
163 /* now applying thread filter for 'bash' */
164 evsel->hists.thread_filter = fake_samples[9].thread;
165 hists__filter_by_thread(hists);
168 pr_info("Histogram for thread filter\n");
169 print_hists_out(hists);
172 /* normal stats should be invariant */
173 TEST_ASSERT_VAL("Invalid nr samples",
174 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
175 TEST_ASSERT_VAL("Invalid nr hist entries",
176 hists->nr_entries == 9);
177 TEST_ASSERT_VAL("Invalid total period",
178 hists->stats.total_period == 1000);
180 /* but filter stats are changed */
181 TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
182 hists->stats.nr_non_filtered_samples == 4);
183 TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
184 hists->nr_non_filtered_entries == 4);
185 TEST_ASSERT_VAL("Unmatched total period for thread filter",
186 hists->stats.total_non_filtered_period == 400);
188 /* remove thread filter first */
189 evsel->hists.thread_filter = NULL;
190 hists__filter_by_thread(hists);
192 /* now applying dso filter for 'kernel' */
193 evsel->hists.dso_filter = fake_samples[0].map->dso;
194 hists__filter_by_dso(hists);
197 pr_info("Histogram for dso filter\n");
198 print_hists_out(hists);
201 /* normal stats should be invariant */
202 TEST_ASSERT_VAL("Invalid nr samples",
203 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
204 TEST_ASSERT_VAL("Invalid nr hist entries",
205 hists->nr_entries == 9);
206 TEST_ASSERT_VAL("Invalid total period",
207 hists->stats.total_period == 1000);
209 /* but filter stats are changed */
210 TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
211 hists->stats.nr_non_filtered_samples == 3);
212 TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
213 hists->nr_non_filtered_entries == 3);
214 TEST_ASSERT_VAL("Unmatched total period for dso filter",
215 hists->stats.total_non_filtered_period == 300);
217 /* remove dso filter first */
218 evsel->hists.dso_filter = NULL;
219 hists__filter_by_dso(hists);
222 * now applying symbol filter for 'main'. Also note that
223 * there's 3 samples that have 'main' symbol but the 4th
224 * entry of fake_samples was collapsed already so it won't
225 * be counted as a separate entry but the sample count and
226 * total period will be remained.
228 evsel->hists.symbol_filter_str = "main";
229 hists__filter_by_symbol(hists);
232 pr_info("Histogram for symbol filter\n");
233 print_hists_out(hists);
236 /* normal stats should be invariant */
237 TEST_ASSERT_VAL("Invalid nr samples",
238 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
239 TEST_ASSERT_VAL("Invalid nr hist entries",
240 hists->nr_entries == 9);
241 TEST_ASSERT_VAL("Invalid total period",
242 hists->stats.total_period == 1000);
244 /* but filter stats are changed */
245 TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
246 hists->stats.nr_non_filtered_samples == 3);
247 TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
248 hists->nr_non_filtered_entries == 2);
249 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
250 hists->stats.total_non_filtered_period == 300);
252 /* now applying all filters at once. */
253 evsel->hists.thread_filter = fake_samples[1].thread;
254 evsel->hists.dso_filter = fake_samples[1].map->dso;
255 hists__filter_by_thread(hists);
256 hists__filter_by_dso(hists);
259 pr_info("Histogram for all filters\n");
260 print_hists_out(hists);
263 /* normal stats should be invariant */
264 TEST_ASSERT_VAL("Invalid nr samples",
265 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
266 TEST_ASSERT_VAL("Invalid nr hist entries",
267 hists->nr_entries == 9);
268 TEST_ASSERT_VAL("Invalid total period",
269 hists->stats.total_period == 1000);
271 /* but filter stats are changed */
272 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
273 hists->stats.nr_non_filtered_samples == 2);
274 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
275 hists->nr_non_filtered_entries == 1);
276 TEST_ASSERT_VAL("Unmatched total period for all filter",
277 hists->stats.total_non_filtered_period == 200);
284 /* tear down everything */
285 perf_evlist__delete(evlist);
286 reset_output_field();
287 machines__exit(&machines);