1 // SPDX-License-Identifier: GPL-2.0
2 #include "util/debug.h"
3 #include "util/dso.h"
4 #include "util/event.h"
5 #include "util/map.h"
6 #include "util/symbol.h"
7 #include "util/sort.h"
8 #include "util/evsel.h"
9 #include "util/evlist.h"
10 #include "util/machine.h"
11 #include "util/parse-events.h"
12 #include "util/thread.h"
13 #include "tests/tests.h"
14 #include "tests/hists_common.h"
15 #include <linux/kernel.h>
16
17 struct sample {
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 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, },
29 /* perf [perf] main() */
30 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, },
31 /* perf [perf] cmd_record() */
32 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, },
33 /* perf [libc] malloc() */
34 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, },
35 /* perf [libc] free() */
36 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, },
37 /* perf [perf] main() */
38 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, },
39 /* perf [kernel] page_fault() */
40 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
41 /* bash [bash] main() */
42 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, },
43 /* bash [bash] xmalloc() */
44 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, },
45 /* bash [kernel] page_fault() */
46 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
47 };
48
49 /*
50 * Will be cast to struct ip_callchain which has all 64 bit entries
51 * of nr and ips[].
52 */
53 static u64 fake_callchains[][10] = {
54 /* schedule => run_command => main */
55 { 3, FAKE_IP_KERNEL_SCHEDULE, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
56 /* main */
57 { 1, FAKE_IP_PERF_MAIN, },
58 /* cmd_record => run_command => main */
59 { 3, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
60 /* malloc => cmd_record => run_command => main */
61 { 4, FAKE_IP_LIBC_MALLOC, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND,
62 FAKE_IP_PERF_MAIN, },
63 /* free => cmd_record => run_command => main */
64 { 4, FAKE_IP_LIBC_FREE, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND,
65 FAKE_IP_PERF_MAIN, },
66 /* main */
67 { 1, FAKE_IP_PERF_MAIN, },
68 /* page_fault => sys_perf_event_open => run_command => main */
69 { 4, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_KERNEL_SYS_PERF_EVENT_OPEN,
70 FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
71 /* main */
72 { 1, FAKE_IP_BASH_MAIN, },
73 /* xmalloc => malloc => xmalloc => malloc => xmalloc => main */
74 { 6, FAKE_IP_BASH_XMALLOC, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC,
75 FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC, FAKE_IP_BASH_MAIN, },
76 /* page_fault => malloc => main */
77 { 3, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_MAIN, },
78 };
79
add_hist_entries(struct hists * hists,struct machine * machine)80 static int add_hist_entries(struct hists *hists, struct machine *machine)
81 {
82 struct addr_location al;
83 struct evsel *evsel = hists_to_evsel(hists);
84 struct perf_sample sample = { .period = 1000, };
85 size_t i;
86
87 addr_location__init(&al);
88 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
89 struct hist_entry_iter iter = {
90 .evsel = evsel,
91 .sample = &sample,
92 .hide_unresolved = false,
93 };
94
95 if (symbol_conf.cumulate_callchain)
96 iter.ops = &hist_iter_cumulative;
97 else
98 iter.ops = &hist_iter_normal;
99
100 sample.cpumode = PERF_RECORD_MISC_USER;
101 sample.pid = fake_samples[i].pid;
102 sample.tid = fake_samples[i].pid;
103 sample.ip = fake_samples[i].ip;
104 sample.callchain = (struct ip_callchain *)fake_callchains[i];
105
106 if (machine__resolve(machine, &al, &sample) < 0)
107 goto out;
108
109 if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
110 NULL) < 0) {
111 goto out;
112 }
113
114 thread__put(fake_samples[i].thread);
115 fake_samples[i].thread = thread__get(al.thread);
116 map__put(fake_samples[i].map);
117 fake_samples[i].map = map__get(al.map);
118 fake_samples[i].sym = al.sym;
119 }
120
121 addr_location__exit(&al);
122 return TEST_OK;
123
124 out:
125 pr_debug("Not enough memory for adding a hist entry\n");
126 addr_location__exit(&al);
127 return TEST_FAIL;
128 }
129
del_hist_entries(struct hists * hists)130 static void del_hist_entries(struct hists *hists)
131 {
132 struct hist_entry *he;
133 struct rb_root_cached *root_in;
134 struct rb_root_cached *root_out;
135 struct rb_node *node;
136
137 if (hists__has(hists, need_collapse))
138 root_in = &hists->entries_collapsed;
139 else
140 root_in = hists->entries_in;
141
142 root_out = &hists->entries;
143
144 while (!RB_EMPTY_ROOT(&root_out->rb_root)) {
145 node = rb_first_cached(root_out);
146
147 he = rb_entry(node, struct hist_entry, rb_node);
148 rb_erase_cached(node, root_out);
149 rb_erase_cached(&he->rb_node_in, root_in);
150 hist_entry__delete(he);
151 }
152 }
153
put_fake_samples(void)154 static void put_fake_samples(void)
155 {
156 size_t i;
157
158 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
159 map__zput(fake_samples[i].map);
160 thread__zput(fake_samples[i].thread);
161 }
162 }
163
164 typedef int (*test_fn_t)(struct evsel *, struct machine *);
165
166 #define COMM(he) (thread__comm_str(he->thread))
167 #define DSO(he) (map__dso(he->ms.map)->short_name)
168 #define SYM(he) (he->ms.sym->name)
169 #define CPU(he) (he->cpu)
170 #define DEPTH(he) (he->callchain->max_depth)
171 #define CDSO(cl) (map__dso(cl->ms.map)->short_name)
172 #define CSYM(cl) (cl->ms.sym->name)
173
174 struct result {
175 u64 children;
176 u64 self;
177 const char *comm;
178 const char *dso;
179 const char *sym;
180 };
181
182 struct callchain_result {
183 u64 nr;
184 struct {
185 const char *dso;
186 const char *sym;
187 } node[10];
188 };
189
do_test(struct hists * hists,struct result * expected,size_t nr_expected,struct callchain_result * expected_callchain,size_t nr_callchain)190 static int do_test(struct hists *hists, struct result *expected, size_t nr_expected,
191 struct callchain_result *expected_callchain, size_t nr_callchain)
192 {
193 char buf[32];
194 size_t i, c;
195 struct hist_entry *he;
196 struct rb_root *root;
197 struct rb_node *node;
198 struct callchain_node *cnode;
199 struct callchain_list *clist;
200
201 /*
202 * adding and deleting hist entries must be done outside of this
203 * function since TEST_ASSERT_VAL() returns in case of failure.
204 */
205 hists__collapse_resort(hists, NULL);
206 evsel__output_resort(hists_to_evsel(hists), NULL);
207
208 if (verbose > 2) {
209 pr_info("use callchain: %d, cumulate callchain: %d\n",
210 symbol_conf.use_callchain,
211 symbol_conf.cumulate_callchain);
212 print_hists_out(hists);
213 }
214
215 root = &hists->entries.rb_root;
216 for (node = rb_first(root), i = 0;
217 node && (he = rb_entry(node, struct hist_entry, rb_node));
218 node = rb_next(node), i++) {
219 scnprintf(buf, sizeof(buf), "Invalid hist entry #%zd", i);
220
221 TEST_ASSERT_VAL("Incorrect number of hist entry",
222 i < nr_expected);
223 TEST_ASSERT_VAL(buf, he->stat.period == expected[i].self &&
224 !strcmp(COMM(he), expected[i].comm) &&
225 !strcmp(DSO(he), expected[i].dso) &&
226 !strcmp(SYM(he), expected[i].sym));
227
228 if (symbol_conf.cumulate_callchain)
229 TEST_ASSERT_VAL(buf, he->stat_acc->period == expected[i].children);
230
231 if (!symbol_conf.use_callchain)
232 continue;
233
234 /* check callchain entries */
235 root = &he->callchain->node.rb_root;
236
237 TEST_ASSERT_VAL("callchains expected", !RB_EMPTY_ROOT(root));
238 cnode = rb_entry(rb_first(root), struct callchain_node, rb_node);
239
240 c = 0;
241 list_for_each_entry(clist, &cnode->val, list) {
242 scnprintf(buf, sizeof(buf), "Invalid callchain entry #%zd/%zd", i, c);
243
244 TEST_ASSERT_VAL("Incorrect number of callchain entry",
245 c < expected_callchain[i].nr);
246 TEST_ASSERT_VAL(buf,
247 !strcmp(CDSO(clist), expected_callchain[i].node[c].dso) &&
248 !strcmp(CSYM(clist), expected_callchain[i].node[c].sym));
249 c++;
250 }
251 /* TODO: handle multiple child nodes properly */
252 TEST_ASSERT_VAL("Incorrect number of callchain entry",
253 c <= expected_callchain[i].nr);
254 }
255 TEST_ASSERT_VAL("Incorrect number of hist entry",
256 i == nr_expected);
257 TEST_ASSERT_VAL("Incorrect number of callchain entry",
258 !symbol_conf.use_callchain || nr_expected == nr_callchain);
259 return 0;
260 }
261
262 /* NO callchain + NO children */
test1(struct evsel * evsel,struct machine * machine)263 static int test1(struct evsel *evsel, struct machine *machine)
264 {
265 int err;
266 struct hists *hists = evsel__hists(evsel);
267 /*
268 * expected output:
269 *
270 * Overhead Command Shared Object Symbol
271 * ======== ======= ============= ==============
272 * 20.00% perf perf [.] main
273 * 10.00% bash [kernel] [k] page_fault
274 * 10.00% bash bash [.] main
275 * 10.00% bash bash [.] xmalloc
276 * 10.00% perf [kernel] [k] page_fault
277 * 10.00% perf [kernel] [k] schedule
278 * 10.00% perf libc [.] free
279 * 10.00% perf libc [.] malloc
280 * 10.00% perf perf [.] cmd_record
281 */
282 struct result expected[] = {
283 { 0, 2000, "perf", "perf", "main" },
284 { 0, 1000, "bash", "[kernel]", "page_fault" },
285 { 0, 1000, "bash", "bash", "main" },
286 { 0, 1000, "bash", "bash", "xmalloc" },
287 { 0, 1000, "perf", "[kernel]", "page_fault" },
288 { 0, 1000, "perf", "[kernel]", "schedule" },
289 { 0, 1000, "perf", "libc", "free" },
290 { 0, 1000, "perf", "libc", "malloc" },
291 { 0, 1000, "perf", "perf", "cmd_record" },
292 };
293
294 symbol_conf.use_callchain = false;
295 symbol_conf.cumulate_callchain = false;
296 evsel__reset_sample_bit(evsel, CALLCHAIN);
297
298 setup_sorting(NULL);
299 callchain_register_param(&callchain_param);
300
301 err = add_hist_entries(hists, machine);
302 if (err < 0)
303 goto out;
304
305 err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0);
306
307 out:
308 del_hist_entries(hists);
309 reset_output_field();
310 return err;
311 }
312
313 /* callchain + NO children */
test2(struct evsel * evsel,struct machine * machine)314 static int test2(struct evsel *evsel, struct machine *machine)
315 {
316 int err;
317 struct hists *hists = evsel__hists(evsel);
318 /*
319 * expected output:
320 *
321 * Overhead Command Shared Object Symbol
322 * ======== ======= ============= ==============
323 * 20.00% perf perf [.] main
324 * |
325 * --- main
326 *
327 * 10.00% bash [kernel] [k] page_fault
328 * |
329 * --- page_fault
330 * malloc
331 * main
332 *
333 * 10.00% bash bash [.] main
334 * |
335 * --- main
336 *
337 * 10.00% bash bash [.] xmalloc
338 * |
339 * --- xmalloc
340 * malloc
341 * xmalloc <--- NOTE: there's a cycle
342 * malloc
343 * xmalloc
344 * main
345 *
346 * 10.00% perf [kernel] [k] page_fault
347 * |
348 * --- page_fault
349 * sys_perf_event_open
350 * run_command
351 * main
352 *
353 * 10.00% perf [kernel] [k] schedule
354 * |
355 * --- schedule
356 * run_command
357 * main
358 *
359 * 10.00% perf libc [.] free
360 * |
361 * --- free
362 * cmd_record
363 * run_command
364 * main
365 *
366 * 10.00% perf libc [.] malloc
367 * |
368 * --- malloc
369 * cmd_record
370 * run_command
371 * main
372 *
373 * 10.00% perf perf [.] cmd_record
374 * |
375 * --- cmd_record
376 * run_command
377 * main
378 *
379 */
380 struct result expected[] = {
381 { 0, 2000, "perf", "perf", "main" },
382 { 0, 1000, "bash", "[kernel]", "page_fault" },
383 { 0, 1000, "bash", "bash", "main" },
384 { 0, 1000, "bash", "bash", "xmalloc" },
385 { 0, 1000, "perf", "[kernel]", "page_fault" },
386 { 0, 1000, "perf", "[kernel]", "schedule" },
387 { 0, 1000, "perf", "libc", "free" },
388 { 0, 1000, "perf", "libc", "malloc" },
389 { 0, 1000, "perf", "perf", "cmd_record" },
390 };
391 struct callchain_result expected_callchain[] = {
392 {
393 1, { { "perf", "main" }, },
394 },
395 {
396 3, { { "[kernel]", "page_fault" },
397 { "libc", "malloc" },
398 { "bash", "main" }, },
399 },
400 {
401 1, { { "bash", "main" }, },
402 },
403 {
404 6, { { "bash", "xmalloc" },
405 { "libc", "malloc" },
406 { "bash", "xmalloc" },
407 { "libc", "malloc" },
408 { "bash", "xmalloc" },
409 { "bash", "main" }, },
410 },
411 {
412 4, { { "[kernel]", "page_fault" },
413 { "[kernel]", "sys_perf_event_open" },
414 { "perf", "run_command" },
415 { "perf", "main" }, },
416 },
417 {
418 3, { { "[kernel]", "schedule" },
419 { "perf", "run_command" },
420 { "perf", "main" }, },
421 },
422 {
423 4, { { "libc", "free" },
424 { "perf", "cmd_record" },
425 { "perf", "run_command" },
426 { "perf", "main" }, },
427 },
428 {
429 4, { { "libc", "malloc" },
430 { "perf", "cmd_record" },
431 { "perf", "run_command" },
432 { "perf", "main" }, },
433 },
434 {
435 3, { { "perf", "cmd_record" },
436 { "perf", "run_command" },
437 { "perf", "main" }, },
438 },
439 };
440
441 symbol_conf.use_callchain = true;
442 symbol_conf.cumulate_callchain = false;
443 evsel__set_sample_bit(evsel, CALLCHAIN);
444
445 setup_sorting(NULL);
446 callchain_register_param(&callchain_param);
447
448 err = add_hist_entries(hists, machine);
449 if (err < 0)
450 goto out;
451
452 err = do_test(hists, expected, ARRAY_SIZE(expected),
453 expected_callchain, ARRAY_SIZE(expected_callchain));
454
455 out:
456 del_hist_entries(hists);
457 reset_output_field();
458 return err;
459 }
460
461 /* NO callchain + children */
test3(struct evsel * evsel,struct machine * machine)462 static int test3(struct evsel *evsel, struct machine *machine)
463 {
464 int err;
465 struct hists *hists = evsel__hists(evsel);
466 /*
467 * expected output:
468 *
469 * Children Self Command Shared Object Symbol
470 * ======== ======== ======= ============= =======================
471 * 70.00% 20.00% perf perf [.] main
472 * 50.00% 0.00% perf perf [.] run_command
473 * 30.00% 10.00% bash bash [.] main
474 * 30.00% 10.00% perf perf [.] cmd_record
475 * 20.00% 0.00% bash libc [.] malloc
476 * 10.00% 10.00% bash [kernel] [k] page_fault
477 * 10.00% 10.00% bash bash [.] xmalloc
478 * 10.00% 10.00% perf [kernel] [k] page_fault
479 * 10.00% 10.00% perf libc [.] malloc
480 * 10.00% 10.00% perf [kernel] [k] schedule
481 * 10.00% 10.00% perf libc [.] free
482 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
483 */
484 struct result expected[] = {
485 { 7000, 2000, "perf", "perf", "main" },
486 { 5000, 0, "perf", "perf", "run_command" },
487 { 3000, 1000, "bash", "bash", "main" },
488 { 3000, 1000, "perf", "perf", "cmd_record" },
489 { 2000, 0, "bash", "libc", "malloc" },
490 { 1000, 1000, "bash", "[kernel]", "page_fault" },
491 { 1000, 1000, "bash", "bash", "xmalloc" },
492 { 1000, 1000, "perf", "[kernel]", "page_fault" },
493 { 1000, 1000, "perf", "[kernel]", "schedule" },
494 { 1000, 1000, "perf", "libc", "free" },
495 { 1000, 1000, "perf", "libc", "malloc" },
496 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
497 };
498
499 symbol_conf.use_callchain = false;
500 symbol_conf.cumulate_callchain = true;
501 evsel__reset_sample_bit(evsel, CALLCHAIN);
502
503 setup_sorting(NULL);
504 callchain_register_param(&callchain_param);
505
506 err = add_hist_entries(hists, machine);
507 if (err < 0)
508 goto out;
509
510 err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0);
511
512 out:
513 del_hist_entries(hists);
514 reset_output_field();
515 return err;
516 }
517
518 /* callchain + children */
test4(struct evsel * evsel,struct machine * machine)519 static int test4(struct evsel *evsel, struct machine *machine)
520 {
521 int err;
522 struct hists *hists = evsel__hists(evsel);
523 /*
524 * expected output:
525 *
526 * Children Self Command Shared Object Symbol
527 * ======== ======== ======= ============= =======================
528 * 70.00% 20.00% perf perf [.] main
529 * |
530 * --- main
531 *
532 * 50.00% 0.00% perf perf [.] run_command
533 * |
534 * --- run_command
535 * main
536 *
537 * 30.00% 10.00% bash bash [.] main
538 * |
539 * --- main
540 *
541 * 30.00% 10.00% perf perf [.] cmd_record
542 * |
543 * --- cmd_record
544 * run_command
545 * main
546 *
547 * 20.00% 0.00% bash libc [.] malloc
548 * |
549 * --- malloc
550 * |
551 * |--50.00%-- xmalloc
552 * | main
553 * --50.00%-- main
554 *
555 * 10.00% 10.00% bash [kernel] [k] page_fault
556 * |
557 * --- page_fault
558 * malloc
559 * main
560 *
561 * 10.00% 10.00% bash bash [.] xmalloc
562 * |
563 * --- xmalloc
564 * malloc
565 * xmalloc <--- NOTE: there's a cycle
566 * malloc
567 * xmalloc
568 * main
569 *
570 * 10.00% 0.00% perf [kernel] [k] sys_perf_event_open
571 * |
572 * --- sys_perf_event_open
573 * run_command
574 * main
575 *
576 * 10.00% 10.00% perf [kernel] [k] page_fault
577 * |
578 * --- page_fault
579 * sys_perf_event_open
580 * run_command
581 * main
582 *
583 * 10.00% 10.00% perf [kernel] [k] schedule
584 * |
585 * --- schedule
586 * run_command
587 * main
588 *
589 * 10.00% 10.00% perf libc [.] free
590 * |
591 * --- free
592 * cmd_record
593 * run_command
594 * main
595 *
596 * 10.00% 10.00% perf libc [.] malloc
597 * |
598 * --- malloc
599 * cmd_record
600 * run_command
601 * main
602 *
603 */
604 struct result expected[] = {
605 { 7000, 2000, "perf", "perf", "main" },
606 { 5000, 0, "perf", "perf", "run_command" },
607 { 3000, 1000, "bash", "bash", "main" },
608 { 3000, 1000, "perf", "perf", "cmd_record" },
609 { 2000, 0, "bash", "libc", "malloc" },
610 { 1000, 1000, "bash", "[kernel]", "page_fault" },
611 { 1000, 1000, "bash", "bash", "xmalloc" },
612 { 1000, 0, "perf", "[kernel]", "sys_perf_event_open" },
613 { 1000, 1000, "perf", "[kernel]", "page_fault" },
614 { 1000, 1000, "perf", "[kernel]", "schedule" },
615 { 1000, 1000, "perf", "libc", "free" },
616 { 1000, 1000, "perf", "libc", "malloc" },
617 };
618 struct callchain_result expected_callchain[] = {
619 {
620 1, { { "perf", "main" }, },
621 },
622 {
623 2, { { "perf", "run_command" },
624 { "perf", "main" }, },
625 },
626 {
627 1, { { "bash", "main" }, },
628 },
629 {
630 3, { { "perf", "cmd_record" },
631 { "perf", "run_command" },
632 { "perf", "main" }, },
633 },
634 {
635 4, { { "libc", "malloc" },
636 { "bash", "xmalloc" },
637 { "bash", "main" },
638 { "bash", "main" }, },
639 },
640 {
641 3, { { "[kernel]", "page_fault" },
642 { "libc", "malloc" },
643 { "bash", "main" }, },
644 },
645 {
646 6, { { "bash", "xmalloc" },
647 { "libc", "malloc" },
648 { "bash", "xmalloc" },
649 { "libc", "malloc" },
650 { "bash", "xmalloc" },
651 { "bash", "main" }, },
652 },
653 {
654 3, { { "[kernel]", "sys_perf_event_open" },
655 { "perf", "run_command" },
656 { "perf", "main" }, },
657 },
658 {
659 4, { { "[kernel]", "page_fault" },
660 { "[kernel]", "sys_perf_event_open" },
661 { "perf", "run_command" },
662 { "perf", "main" }, },
663 },
664 {
665 3, { { "[kernel]", "schedule" },
666 { "perf", "run_command" },
667 { "perf", "main" }, },
668 },
669 {
670 4, { { "libc", "free" },
671 { "perf", "cmd_record" },
672 { "perf", "run_command" },
673 { "perf", "main" }, },
674 },
675 {
676 4, { { "libc", "malloc" },
677 { "perf", "cmd_record" },
678 { "perf", "run_command" },
679 { "perf", "main" }, },
680 },
681 };
682
683 symbol_conf.use_callchain = true;
684 symbol_conf.cumulate_callchain = true;
685 evsel__set_sample_bit(evsel, CALLCHAIN);
686
687 setup_sorting(NULL);
688
689 callchain_param = callchain_param_default;
690 callchain_register_param(&callchain_param);
691
692 err = add_hist_entries(hists, machine);
693 if (err < 0)
694 goto out;
695
696 err = do_test(hists, expected, ARRAY_SIZE(expected),
697 expected_callchain, ARRAY_SIZE(expected_callchain));
698
699 out:
700 del_hist_entries(hists);
701 reset_output_field();
702 return err;
703 }
704
test__hists_cumulate(struct test_suite * test __maybe_unused,int subtest __maybe_unused)705 static int test__hists_cumulate(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
706 {
707 int err = TEST_FAIL;
708 struct machines machines;
709 struct machine *machine;
710 struct evsel *evsel;
711 struct evlist *evlist = evlist__new();
712 size_t i;
713 test_fn_t testcases[] = {
714 test1,
715 test2,
716 test3,
717 test4,
718 };
719
720 TEST_ASSERT_VAL("No memory", evlist);
721
722 err = parse_event(evlist, "cpu-clock");
723 if (err)
724 goto out;
725 err = TEST_FAIL;
726
727 machines__init(&machines);
728
729 /* setup threads/dso/map/symbols also */
730 machine = setup_fake_machine(&machines);
731 if (!machine)
732 goto out;
733
734 if (verbose > 1)
735 machine__fprintf(machine, stderr);
736
737 evsel = evlist__first(evlist);
738
739 for (i = 0; i < ARRAY_SIZE(testcases); i++) {
740 err = testcases[i](evsel, machine);
741 if (err < 0)
742 break;
743 }
744
745 out:
746 /* tear down everything */
747 evlist__delete(evlist);
748 machines__exit(&machines);
749 put_fake_samples();
750
751 return err;
752 }
753
754 DEFINE_SUITE("Cumulate child hist entries", hists_cumulate);
755