xref: /openbmc/linux/tools/perf/tests/hists_output.c (revision bb0eb050)
1 #include "perf.h"
2 #include "util/debug.h"
3 #include "util/event.h"
4 #include "util/symbol.h"
5 #include "util/sort.h"
6 #include "util/evsel.h"
7 #include "util/evlist.h"
8 #include "util/machine.h"
9 #include "util/thread.h"
10 #include "util/parse-events.h"
11 #include "tests/tests.h"
12 #include "tests/hists_common.h"
13 #include <linux/kernel.h>
14 
15 struct sample {
16 	u32 cpu;
17 	u32 pid;
18 	u64 ip;
19 	struct thread *thread;
20 	struct map *map;
21 	struct symbol *sym;
22 };
23 
24 /* For the numbers, see hists_common.c */
25 static struct sample fake_samples[] = {
26 	/* perf [kernel] schedule() */
27 	{ .cpu = 0, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, },
28 	/* perf [perf]   main() */
29 	{ .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, },
30 	/* perf [perf]   cmd_record() */
31 	{ .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, },
32 	/* perf [libc]   malloc() */
33 	{ .cpu = 1, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, },
34 	/* perf [libc]   free() */
35 	{ .cpu = 2, .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, },
36 	/* perf [perf]   main() */
37 	{ .cpu = 2, .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, },
38 	/* perf [kernel] page_fault() */
39 	{ .cpu = 2, .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
40 	/* bash [bash]   main() */
41 	{ .cpu = 3, .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_MAIN, },
42 	/* bash [bash]   xmalloc() */
43 	{ .cpu = 0, .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_XMALLOC, },
44 	/* bash [kernel] page_fault() */
45 	{ .cpu = 1, .pid = FAKE_PID_BASH,  .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
46 };
47 
48 static int add_hist_entries(struct hists *hists, struct machine *machine)
49 {
50 	struct addr_location al;
51 	struct perf_evsel *evsel = hists_to_evsel(hists);
52 	struct perf_sample sample = { .period = 100, };
53 	size_t i;
54 
55 	for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
56 		struct hist_entry_iter iter = {
57 			.evsel = evsel,
58 			.sample = &sample,
59 			.ops = &hist_iter_normal,
60 			.hide_unresolved = false,
61 		};
62 
63 		sample.cpumode = PERF_RECORD_MISC_USER;
64 		sample.cpu = fake_samples[i].cpu;
65 		sample.pid = fake_samples[i].pid;
66 		sample.tid = fake_samples[i].pid;
67 		sample.ip = fake_samples[i].ip;
68 
69 		if (machine__resolve(machine, &al, &sample) < 0)
70 			goto out;
71 
72 		if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
73 					 NULL) < 0) {
74 			addr_location__put(&al);
75 			goto out;
76 		}
77 
78 		fake_samples[i].thread = al.thread;
79 		fake_samples[i].map = al.map;
80 		fake_samples[i].sym = al.sym;
81 	}
82 
83 	return TEST_OK;
84 
85 out:
86 	pr_debug("Not enough memory for adding a hist entry\n");
87 	return TEST_FAIL;
88 }
89 
90 static void del_hist_entries(struct hists *hists)
91 {
92 	struct hist_entry *he;
93 	struct rb_root *root_in;
94 	struct rb_root *root_out;
95 	struct rb_node *node;
96 
97 	if (hists__has(hists, need_collapse))
98 		root_in = &hists->entries_collapsed;
99 	else
100 		root_in = hists->entries_in;
101 
102 	root_out = &hists->entries;
103 
104 	while (!RB_EMPTY_ROOT(root_out)) {
105 		node = rb_first(root_out);
106 
107 		he = rb_entry(node, struct hist_entry, rb_node);
108 		rb_erase(node, root_out);
109 		rb_erase(&he->rb_node_in, root_in);
110 		hist_entry__delete(he);
111 	}
112 }
113 
114 typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);
115 
116 #define COMM(he)  (thread__comm_str(he->thread))
117 #define DSO(he)   (he->ms.map->dso->short_name)
118 #define SYM(he)   (he->ms.sym->name)
119 #define CPU(he)   (he->cpu)
120 #define PID(he)   (he->thread->tid)
121 
122 /* default sort keys (no field) */
123 static int test1(struct perf_evsel *evsel, struct machine *machine)
124 {
125 	int err;
126 	struct hists *hists = evsel__hists(evsel);
127 	struct hist_entry *he;
128 	struct rb_root *root;
129 	struct rb_node *node;
130 
131 	field_order = NULL;
132 	sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */
133 
134 	setup_sorting(NULL);
135 
136 	/*
137 	 * expected output:
138 	 *
139 	 * Overhead  Command  Shared Object          Symbol
140 	 * ========  =======  =============  ==============
141 	 *   20.00%     perf  perf           [.] main
142 	 *   10.00%     bash  [kernel]       [k] page_fault
143 	 *   10.00%     bash  bash           [.] main
144 	 *   10.00%     bash  bash           [.] xmalloc
145 	 *   10.00%     perf  [kernel]       [k] page_fault
146 	 *   10.00%     perf  [kernel]       [k] schedule
147 	 *   10.00%     perf  libc           [.] free
148 	 *   10.00%     perf  libc           [.] malloc
149 	 *   10.00%     perf  perf           [.] cmd_record
150 	 */
151 	err = add_hist_entries(hists, machine);
152 	if (err < 0)
153 		goto out;
154 
155 	hists__collapse_resort(hists, NULL);
156 	perf_evsel__output_resort(evsel, NULL);
157 
158 	if (verbose > 2) {
159 		pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
160 		print_hists_out(hists);
161 	}
162 
163 	root = &hists->entries;
164 	node = rb_first(root);
165 	he = rb_entry(node, struct hist_entry, rb_node);
166 	TEST_ASSERT_VAL("Invalid hist entry",
167 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") &&
168 			!strcmp(SYM(he), "main") && he->stat.period == 200);
169 
170 	node = rb_next(node);
171 	he = rb_entry(node, struct hist_entry, rb_node);
172 	TEST_ASSERT_VAL("Invalid hist entry",
173 			!strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") &&
174 			!strcmp(SYM(he), "page_fault") && he->stat.period == 100);
175 
176 	node = rb_next(node);
177 	he = rb_entry(node, struct hist_entry, rb_node);
178 	TEST_ASSERT_VAL("Invalid hist entry",
179 			!strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") &&
180 			!strcmp(SYM(he), "main") && he->stat.period == 100);
181 
182 	node = rb_next(node);
183 	he = rb_entry(node, struct hist_entry, rb_node);
184 	TEST_ASSERT_VAL("Invalid hist entry",
185 			!strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") &&
186 			!strcmp(SYM(he), "xmalloc") && he->stat.period == 100);
187 
188 	node = rb_next(node);
189 	he = rb_entry(node, struct hist_entry, rb_node);
190 	TEST_ASSERT_VAL("Invalid hist entry",
191 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") &&
192 			!strcmp(SYM(he), "page_fault") && he->stat.period == 100);
193 
194 	node = rb_next(node);
195 	he = rb_entry(node, struct hist_entry, rb_node);
196 	TEST_ASSERT_VAL("Invalid hist entry",
197 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") &&
198 			!strcmp(SYM(he), "schedule") && he->stat.period == 100);
199 
200 	node = rb_next(node);
201 	he = rb_entry(node, struct hist_entry, rb_node);
202 	TEST_ASSERT_VAL("Invalid hist entry",
203 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") &&
204 			!strcmp(SYM(he), "free") && he->stat.period == 100);
205 
206 	node = rb_next(node);
207 	he = rb_entry(node, struct hist_entry, rb_node);
208 	TEST_ASSERT_VAL("Invalid hist entry",
209 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") &&
210 			!strcmp(SYM(he), "malloc") && he->stat.period == 100);
211 
212 	node = rb_next(node);
213 	he = rb_entry(node, struct hist_entry, rb_node);
214 	TEST_ASSERT_VAL("Invalid hist entry",
215 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") &&
216 			!strcmp(SYM(he), "cmd_record") && he->stat.period == 100);
217 
218 out:
219 	del_hist_entries(hists);
220 	reset_output_field();
221 	return err;
222 }
223 
224 /* mixed fields and sort keys */
225 static int test2(struct perf_evsel *evsel, struct machine *machine)
226 {
227 	int err;
228 	struct hists *hists = evsel__hists(evsel);
229 	struct hist_entry *he;
230 	struct rb_root *root;
231 	struct rb_node *node;
232 
233 	field_order = "overhead,cpu";
234 	sort_order = "pid";
235 
236 	setup_sorting(NULL);
237 
238 	/*
239 	 * expected output:
240 	 *
241 	 * Overhead  CPU  Command:  Pid
242 	 * ========  ===  =============
243 	 *   30.00%    1  perf   :  100
244 	 *   10.00%    0  perf   :  100
245 	 *   10.00%    2  perf   :  100
246 	 *   20.00%    2  perf   :  200
247 	 *   10.00%    0  bash   :  300
248 	 *   10.00%    1  bash   :  300
249 	 *   10.00%    3  bash   :  300
250 	 */
251 	err = add_hist_entries(hists, machine);
252 	if (err < 0)
253 		goto out;
254 
255 	hists__collapse_resort(hists, NULL);
256 	perf_evsel__output_resort(evsel, NULL);
257 
258 	if (verbose > 2) {
259 		pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
260 		print_hists_out(hists);
261 	}
262 
263 	root = &hists->entries;
264 	node = rb_first(root);
265 	he = rb_entry(node, struct hist_entry, rb_node);
266 	TEST_ASSERT_VAL("Invalid hist entry",
267 			CPU(he) == 1 && PID(he) == 100 && he->stat.period == 300);
268 
269 	node = rb_next(node);
270 	he = rb_entry(node, struct hist_entry, rb_node);
271 	TEST_ASSERT_VAL("Invalid hist entry",
272 			CPU(he) == 0 && PID(he) == 100 && he->stat.period == 100);
273 
274 out:
275 	del_hist_entries(hists);
276 	reset_output_field();
277 	return err;
278 }
279 
280 /* fields only (no sort key) */
281 static int test3(struct perf_evsel *evsel, struct machine *machine)
282 {
283 	int err;
284 	struct hists *hists = evsel__hists(evsel);
285 	struct hist_entry *he;
286 	struct rb_root *root;
287 	struct rb_node *node;
288 
289 	field_order = "comm,overhead,dso";
290 	sort_order = NULL;
291 
292 	setup_sorting(NULL);
293 
294 	/*
295 	 * expected output:
296 	 *
297 	 * Command  Overhead  Shared Object
298 	 * =======  ========  =============
299 	 *    bash    20.00%  bash
300 	 *    bash    10.00%  [kernel]
301 	 *    perf    30.00%  perf
302 	 *    perf    20.00%  [kernel]
303 	 *    perf    20.00%  libc
304 	 */
305 	err = add_hist_entries(hists, machine);
306 	if (err < 0)
307 		goto out;
308 
309 	hists__collapse_resort(hists, NULL);
310 	perf_evsel__output_resort(evsel, NULL);
311 
312 	if (verbose > 2) {
313 		pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
314 		print_hists_out(hists);
315 	}
316 
317 	root = &hists->entries;
318 	node = rb_first(root);
319 	he = rb_entry(node, struct hist_entry, rb_node);
320 	TEST_ASSERT_VAL("Invalid hist entry",
321 			!strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") &&
322 			he->stat.period == 200);
323 
324 	node = rb_next(node);
325 	he = rb_entry(node, struct hist_entry, rb_node);
326 	TEST_ASSERT_VAL("Invalid hist entry",
327 			!strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") &&
328 			he->stat.period == 100);
329 
330 	node = rb_next(node);
331 	he = rb_entry(node, struct hist_entry, rb_node);
332 	TEST_ASSERT_VAL("Invalid hist entry",
333 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") &&
334 			he->stat.period == 300);
335 
336 	node = rb_next(node);
337 	he = rb_entry(node, struct hist_entry, rb_node);
338 	TEST_ASSERT_VAL("Invalid hist entry",
339 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") &&
340 			he->stat.period == 200);
341 
342 	node = rb_next(node);
343 	he = rb_entry(node, struct hist_entry, rb_node);
344 	TEST_ASSERT_VAL("Invalid hist entry",
345 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") &&
346 			he->stat.period == 200);
347 
348 out:
349 	del_hist_entries(hists);
350 	reset_output_field();
351 	return err;
352 }
353 
354 /* handle duplicate 'dso' field */
355 static int test4(struct perf_evsel *evsel, struct machine *machine)
356 {
357 	int err;
358 	struct hists *hists = evsel__hists(evsel);
359 	struct hist_entry *he;
360 	struct rb_root *root;
361 	struct rb_node *node;
362 
363 	field_order = "dso,sym,comm,overhead,dso";
364 	sort_order = "sym";
365 
366 	setup_sorting(NULL);
367 
368 	/*
369 	 * expected output:
370 	 *
371 	 * Shared Object          Symbol  Command  Overhead
372 	 * =============  ==============  =======  ========
373 	 *          perf  [.] cmd_record     perf    10.00%
374 	 *          libc  [.] free           perf    10.00%
375 	 *          bash  [.] main           bash    10.00%
376 	 *          perf  [.] main           perf    20.00%
377 	 *          libc  [.] malloc         perf    10.00%
378 	 *      [kernel]  [k] page_fault     bash    10.00%
379 	 *      [kernel]  [k] page_fault     perf    10.00%
380 	 *      [kernel]  [k] schedule       perf    10.00%
381 	 *          bash  [.] xmalloc        bash    10.00%
382 	 */
383 	err = add_hist_entries(hists, machine);
384 	if (err < 0)
385 		goto out;
386 
387 	hists__collapse_resort(hists, NULL);
388 	perf_evsel__output_resort(evsel, NULL);
389 
390 	if (verbose > 2) {
391 		pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
392 		print_hists_out(hists);
393 	}
394 
395 	root = &hists->entries;
396 	node = rb_first(root);
397 	he = rb_entry(node, struct hist_entry, rb_node);
398 	TEST_ASSERT_VAL("Invalid hist entry",
399 			!strcmp(DSO(he), "perf") && !strcmp(SYM(he), "cmd_record") &&
400 			!strcmp(COMM(he), "perf") && he->stat.period == 100);
401 
402 	node = rb_next(node);
403 	he = rb_entry(node, struct hist_entry, rb_node);
404 	TEST_ASSERT_VAL("Invalid hist entry",
405 			!strcmp(DSO(he), "libc") && !strcmp(SYM(he), "free") &&
406 			!strcmp(COMM(he), "perf") && he->stat.period == 100);
407 
408 	node = rb_next(node);
409 	he = rb_entry(node, struct hist_entry, rb_node);
410 	TEST_ASSERT_VAL("Invalid hist entry",
411 			!strcmp(DSO(he), "bash") && !strcmp(SYM(he), "main") &&
412 			!strcmp(COMM(he), "bash") && he->stat.period == 100);
413 
414 	node = rb_next(node);
415 	he = rb_entry(node, struct hist_entry, rb_node);
416 	TEST_ASSERT_VAL("Invalid hist entry",
417 			!strcmp(DSO(he), "perf") && !strcmp(SYM(he), "main") &&
418 			!strcmp(COMM(he), "perf") && he->stat.period == 200);
419 
420 	node = rb_next(node);
421 	he = rb_entry(node, struct hist_entry, rb_node);
422 	TEST_ASSERT_VAL("Invalid hist entry",
423 			!strcmp(DSO(he), "libc") && !strcmp(SYM(he), "malloc") &&
424 			!strcmp(COMM(he), "perf") && he->stat.period == 100);
425 
426 	node = rb_next(node);
427 	he = rb_entry(node, struct hist_entry, rb_node);
428 	TEST_ASSERT_VAL("Invalid hist entry",
429 			!strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "page_fault") &&
430 			!strcmp(COMM(he), "bash") && he->stat.period == 100);
431 
432 	node = rb_next(node);
433 	he = rb_entry(node, struct hist_entry, rb_node);
434 	TEST_ASSERT_VAL("Invalid hist entry",
435 			!strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "page_fault") &&
436 			!strcmp(COMM(he), "perf") && he->stat.period == 100);
437 
438 	node = rb_next(node);
439 	he = rb_entry(node, struct hist_entry, rb_node);
440 	TEST_ASSERT_VAL("Invalid hist entry",
441 			!strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "schedule") &&
442 			!strcmp(COMM(he), "perf") && he->stat.period == 100);
443 
444 	node = rb_next(node);
445 	he = rb_entry(node, struct hist_entry, rb_node);
446 	TEST_ASSERT_VAL("Invalid hist entry",
447 			!strcmp(DSO(he), "bash") && !strcmp(SYM(he), "xmalloc") &&
448 			!strcmp(COMM(he), "bash") && he->stat.period == 100);
449 
450 out:
451 	del_hist_entries(hists);
452 	reset_output_field();
453 	return err;
454 }
455 
456 /* full sort keys w/o overhead field */
457 static int test5(struct perf_evsel *evsel, struct machine *machine)
458 {
459 	int err;
460 	struct hists *hists = evsel__hists(evsel);
461 	struct hist_entry *he;
462 	struct rb_root *root;
463 	struct rb_node *node;
464 
465 	field_order = "cpu,pid,comm,dso,sym";
466 	sort_order = "dso,pid";
467 
468 	setup_sorting(NULL);
469 
470 	/*
471 	 * expected output:
472 	 *
473 	 * CPU  Command:  Pid  Command  Shared Object          Symbol
474 	 * ===  =============  =======  =============  ==============
475 	 *   0     perf:  100     perf       [kernel]  [k] schedule
476 	 *   2     perf:  200     perf       [kernel]  [k] page_fault
477 	 *   1     bash:  300     bash       [kernel]  [k] page_fault
478 	 *   0     bash:  300     bash           bash  [.] xmalloc
479 	 *   3     bash:  300     bash           bash  [.] main
480 	 *   1     perf:  100     perf           libc  [.] malloc
481 	 *   2     perf:  100     perf           libc  [.] free
482 	 *   1     perf:  100     perf           perf  [.] cmd_record
483 	 *   1     perf:  100     perf           perf  [.] main
484 	 *   2     perf:  200     perf           perf  [.] main
485 	 */
486 	err = add_hist_entries(hists, machine);
487 	if (err < 0)
488 		goto out;
489 
490 	hists__collapse_resort(hists, NULL);
491 	perf_evsel__output_resort(evsel, NULL);
492 
493 	if (verbose > 2) {
494 		pr_info("[fields = %s, sort = %s]\n", field_order, sort_order);
495 		print_hists_out(hists);
496 	}
497 
498 	root = &hists->entries;
499 	node = rb_first(root);
500 	he = rb_entry(node, struct hist_entry, rb_node);
501 
502 	TEST_ASSERT_VAL("Invalid hist entry",
503 			CPU(he) == 0 && PID(he) == 100 &&
504 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") &&
505 			!strcmp(SYM(he), "schedule") && he->stat.period == 100);
506 
507 	node = rb_next(node);
508 	he = rb_entry(node, struct hist_entry, rb_node);
509 	TEST_ASSERT_VAL("Invalid hist entry",
510 			CPU(he) == 2 && PID(he) == 200 &&
511 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") &&
512 			!strcmp(SYM(he), "page_fault") && he->stat.period == 100);
513 
514 	node = rb_next(node);
515 	he = rb_entry(node, struct hist_entry, rb_node);
516 	TEST_ASSERT_VAL("Invalid hist entry",
517 			CPU(he) == 1 && PID(he) == 300 &&
518 			!strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") &&
519 			!strcmp(SYM(he), "page_fault") && he->stat.period == 100);
520 
521 	node = rb_next(node);
522 	he = rb_entry(node, struct hist_entry, rb_node);
523 	TEST_ASSERT_VAL("Invalid hist entry",
524 			CPU(he) == 0 && PID(he) == 300 &&
525 			!strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") &&
526 			!strcmp(SYM(he), "xmalloc") && he->stat.period == 100);
527 
528 	node = rb_next(node);
529 	he = rb_entry(node, struct hist_entry, rb_node);
530 	TEST_ASSERT_VAL("Invalid hist entry",
531 			CPU(he) == 3 && PID(he) == 300 &&
532 			!strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") &&
533 			!strcmp(SYM(he), "main") && he->stat.period == 100);
534 
535 	node = rb_next(node);
536 	he = rb_entry(node, struct hist_entry, rb_node);
537 	TEST_ASSERT_VAL("Invalid hist entry",
538 			CPU(he) == 1 && PID(he) == 100 &&
539 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") &&
540 			!strcmp(SYM(he), "malloc") && he->stat.period == 100);
541 
542 	node = rb_next(node);
543 	he = rb_entry(node, struct hist_entry, rb_node);
544 	TEST_ASSERT_VAL("Invalid hist entry",
545 			CPU(he) == 2 && PID(he) == 100 &&
546 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") &&
547 			!strcmp(SYM(he), "free") && he->stat.period == 100);
548 
549 	node = rb_next(node);
550 	he = rb_entry(node, struct hist_entry, rb_node);
551 	TEST_ASSERT_VAL("Invalid hist entry",
552 			CPU(he) == 1 && PID(he) == 100 &&
553 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") &&
554 			!strcmp(SYM(he), "cmd_record") && he->stat.period == 100);
555 
556 	node = rb_next(node);
557 	he = rb_entry(node, struct hist_entry, rb_node);
558 	TEST_ASSERT_VAL("Invalid hist entry",
559 			CPU(he) == 1 && PID(he) == 100 &&
560 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") &&
561 			!strcmp(SYM(he), "main") && he->stat.period == 100);
562 
563 	node = rb_next(node);
564 	he = rb_entry(node, struct hist_entry, rb_node);
565 	TEST_ASSERT_VAL("Invalid hist entry",
566 			CPU(he) == 2 && PID(he) == 200 &&
567 			!strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") &&
568 			!strcmp(SYM(he), "main") && he->stat.period == 100);
569 
570 out:
571 	del_hist_entries(hists);
572 	reset_output_field();
573 	return err;
574 }
575 
576 int test__hists_output(int subtest __maybe_unused)
577 {
578 	int err = TEST_FAIL;
579 	struct machines machines;
580 	struct machine *machine;
581 	struct perf_evsel *evsel;
582 	struct perf_evlist *evlist = perf_evlist__new();
583 	size_t i;
584 	test_fn_t testcases[] = {
585 		test1,
586 		test2,
587 		test3,
588 		test4,
589 		test5,
590 	};
591 
592 	TEST_ASSERT_VAL("No memory", evlist);
593 
594 	err = parse_events(evlist, "cpu-clock", NULL);
595 	if (err)
596 		goto out;
597 	err = TEST_FAIL;
598 
599 	machines__init(&machines);
600 
601 	/* setup threads/dso/map/symbols also */
602 	machine = setup_fake_machine(&machines);
603 	if (!machine)
604 		goto out;
605 
606 	if (verbose > 1)
607 		machine__fprintf(machine, stderr);
608 
609 	evsel = perf_evlist__first(evlist);
610 
611 	for (i = 0; i < ARRAY_SIZE(testcases); i++) {
612 		err = testcases[i](evsel, machine);
613 		if (err < 0)
614 			break;
615 	}
616 
617 out:
618 	/* tear down everything */
619 	perf_evlist__delete(evlist);
620 	machines__exit(&machines);
621 
622 	return err;
623 }
624