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