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