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