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