Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include "util/debug.h"
0003 #include "util/dso.h"
0004 #include "util/event.h"
0005 #include "util/map.h"
0006 #include "util/symbol.h"
0007 #include "util/sort.h"
0008 #include "util/evsel.h"
0009 #include "util/evlist.h"
0010 #include "util/machine.h"
0011 #include "util/thread.h"
0012 #include "util/parse-events.h"
0013 #include "tests/tests.h"
0014 #include "tests/hists_common.h"
0015 #include <linux/kernel.h>
0016 
0017 struct sample {
0018     u32 pid;
0019     u64 ip;
0020     struct thread *thread;
0021     struct map *map;
0022     struct symbol *sym;
0023 };
0024 
0025 /* For the numbers, see hists_common.c */
0026 static struct sample fake_samples[] = {
0027     /* perf [kernel] schedule() */
0028     { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, },
0029     /* perf [perf]   main() */
0030     { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, },
0031     /* perf [perf]   cmd_record() */
0032     { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_CMD_RECORD, },
0033     /* perf [libc]   malloc() */
0034     { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, },
0035     /* perf [libc]   free() */
0036     { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_FREE, },
0037     /* perf [perf]   main() */
0038     { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, },
0039     /* perf [kernel] page_fault() */
0040     { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
0041     /* bash [bash]   main() */
0042     { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_MAIN, },
0043     /* bash [bash]   xmalloc() */
0044     { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_XMALLOC, },
0045     /* bash [kernel] page_fault() */
0046     { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_KERNEL_PAGE_FAULT, },
0047 };
0048 
0049 /*
0050  * Will be cast to struct ip_callchain which has all 64 bit entries
0051  * of nr and ips[].
0052  */
0053 static u64 fake_callchains[][10] = {
0054     /*   schedule => run_command => main */
0055     { 3, FAKE_IP_KERNEL_SCHEDULE, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
0056     /*   main  */
0057     { 1, FAKE_IP_PERF_MAIN, },
0058     /*   cmd_record => run_command => main */
0059     { 3, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
0060     /*   malloc => cmd_record => run_command => main */
0061     { 4, FAKE_IP_LIBC_MALLOC, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND,
0062          FAKE_IP_PERF_MAIN, },
0063     /*   free => cmd_record => run_command => main */
0064     { 4, FAKE_IP_LIBC_FREE, FAKE_IP_PERF_CMD_RECORD, FAKE_IP_PERF_RUN_COMMAND,
0065          FAKE_IP_PERF_MAIN, },
0066     /*   main */
0067     { 1, FAKE_IP_PERF_MAIN, },
0068     /*   page_fault => sys_perf_event_open => run_command => main */
0069     { 4, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_KERNEL_SYS_PERF_EVENT_OPEN,
0070          FAKE_IP_PERF_RUN_COMMAND, FAKE_IP_PERF_MAIN, },
0071     /*   main */
0072     { 1, FAKE_IP_BASH_MAIN, },
0073     /*   xmalloc => malloc => xmalloc => malloc => xmalloc => main */
0074     { 6, FAKE_IP_BASH_XMALLOC, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC,
0075          FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_XMALLOC, FAKE_IP_BASH_MAIN, },
0076     /*   page_fault => malloc => main */
0077     { 3, FAKE_IP_KERNEL_PAGE_FAULT, FAKE_IP_LIBC_MALLOC, FAKE_IP_BASH_MAIN, },
0078 };
0079 
0080 static int add_hist_entries(struct hists *hists, struct machine *machine)
0081 {
0082     struct addr_location al;
0083     struct evsel *evsel = hists_to_evsel(hists);
0084     struct perf_sample sample = { .period = 1000, };
0085     size_t i;
0086 
0087     for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
0088         struct hist_entry_iter iter = {
0089             .evsel = evsel,
0090             .sample = &sample,
0091             .hide_unresolved = false,
0092         };
0093 
0094         if (symbol_conf.cumulate_callchain)
0095             iter.ops = &hist_iter_cumulative;
0096         else
0097             iter.ops = &hist_iter_normal;
0098 
0099         sample.cpumode = PERF_RECORD_MISC_USER;
0100         sample.pid = fake_samples[i].pid;
0101         sample.tid = fake_samples[i].pid;
0102         sample.ip = fake_samples[i].ip;
0103         sample.callchain = (struct ip_callchain *)fake_callchains[i];
0104 
0105         if (machine__resolve(machine, &al, &sample) < 0)
0106             goto out;
0107 
0108         if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
0109                      NULL) < 0) {
0110             addr_location__put(&al);
0111             goto out;
0112         }
0113 
0114         fake_samples[i].thread = al.thread;
0115         fake_samples[i].map = al.map;
0116         fake_samples[i].sym = al.sym;
0117     }
0118 
0119     return TEST_OK;
0120 
0121 out:
0122     pr_debug("Not enough memory for adding a hist entry\n");
0123     return TEST_FAIL;
0124 }
0125 
0126 static void del_hist_entries(struct hists *hists)
0127 {
0128     struct hist_entry *he;
0129     struct rb_root_cached *root_in;
0130     struct rb_root_cached *root_out;
0131     struct rb_node *node;
0132 
0133     if (hists__has(hists, need_collapse))
0134         root_in = &hists->entries_collapsed;
0135     else
0136         root_in = hists->entries_in;
0137 
0138     root_out = &hists->entries;
0139 
0140     while (!RB_EMPTY_ROOT(&root_out->rb_root)) {
0141         node = rb_first_cached(root_out);
0142 
0143         he = rb_entry(node, struct hist_entry, rb_node);
0144         rb_erase_cached(node, root_out);
0145         rb_erase_cached(&he->rb_node_in, root_in);
0146         hist_entry__delete(he);
0147     }
0148 }
0149 
0150 typedef int (*test_fn_t)(struct evsel *, struct machine *);
0151 
0152 #define COMM(he)  (thread__comm_str(he->thread))
0153 #define DSO(he)   (he->ms.map->dso->short_name)
0154 #define SYM(he)   (he->ms.sym->name)
0155 #define CPU(he)   (he->cpu)
0156 #define PID(he)   (he->thread->tid)
0157 #define DEPTH(he) (he->callchain->max_depth)
0158 #define CDSO(cl)  (cl->ms.map->dso->short_name)
0159 #define CSYM(cl)  (cl->ms.sym->name)
0160 
0161 struct result {
0162     u64 children;
0163     u64 self;
0164     const char *comm;
0165     const char *dso;
0166     const char *sym;
0167 };
0168 
0169 struct callchain_result {
0170     u64 nr;
0171     struct {
0172         const char *dso;
0173         const char *sym;
0174     } node[10];
0175 };
0176 
0177 static int do_test(struct hists *hists, struct result *expected, size_t nr_expected,
0178            struct callchain_result *expected_callchain, size_t nr_callchain)
0179 {
0180     char buf[32];
0181     size_t i, c;
0182     struct hist_entry *he;
0183     struct rb_root *root;
0184     struct rb_node *node;
0185     struct callchain_node *cnode;
0186     struct callchain_list *clist;
0187 
0188     /*
0189      * adding and deleting hist entries must be done outside of this
0190      * function since TEST_ASSERT_VAL() returns in case of failure.
0191      */
0192     hists__collapse_resort(hists, NULL);
0193     evsel__output_resort(hists_to_evsel(hists), NULL);
0194 
0195     if (verbose > 2) {
0196         pr_info("use callchain: %d, cumulate callchain: %d\n",
0197             symbol_conf.use_callchain,
0198             symbol_conf.cumulate_callchain);
0199         print_hists_out(hists);
0200     }
0201 
0202     root = &hists->entries.rb_root;
0203     for (node = rb_first(root), i = 0;
0204          node && (he = rb_entry(node, struct hist_entry, rb_node));
0205          node = rb_next(node), i++) {
0206         scnprintf(buf, sizeof(buf), "Invalid hist entry #%zd", i);
0207 
0208         TEST_ASSERT_VAL("Incorrect number of hist entry",
0209                 i < nr_expected);
0210         TEST_ASSERT_VAL(buf, he->stat.period == expected[i].self &&
0211                 !strcmp(COMM(he), expected[i].comm) &&
0212                 !strcmp(DSO(he), expected[i].dso) &&
0213                 !strcmp(SYM(he), expected[i].sym));
0214 
0215         if (symbol_conf.cumulate_callchain)
0216             TEST_ASSERT_VAL(buf, he->stat_acc->period == expected[i].children);
0217 
0218         if (!symbol_conf.use_callchain)
0219             continue;
0220 
0221         /* check callchain entries */
0222         root = &he->callchain->node.rb_root;
0223 
0224         TEST_ASSERT_VAL("callchains expected", !RB_EMPTY_ROOT(root));
0225         cnode = rb_entry(rb_first(root), struct callchain_node, rb_node);
0226 
0227         c = 0;
0228         list_for_each_entry(clist, &cnode->val, list) {
0229             scnprintf(buf, sizeof(buf), "Invalid callchain entry #%zd/%zd", i, c);
0230 
0231             TEST_ASSERT_VAL("Incorrect number of callchain entry",
0232                     c < expected_callchain[i].nr);
0233             TEST_ASSERT_VAL(buf,
0234                 !strcmp(CDSO(clist), expected_callchain[i].node[c].dso) &&
0235                 !strcmp(CSYM(clist), expected_callchain[i].node[c].sym));
0236             c++;
0237         }
0238         /* TODO: handle multiple child nodes properly */
0239         TEST_ASSERT_VAL("Incorrect number of callchain entry",
0240                 c <= expected_callchain[i].nr);
0241     }
0242     TEST_ASSERT_VAL("Incorrect number of hist entry",
0243             i == nr_expected);
0244     TEST_ASSERT_VAL("Incorrect number of callchain entry",
0245             !symbol_conf.use_callchain || nr_expected == nr_callchain);
0246     return 0;
0247 }
0248 
0249 /* NO callchain + NO children */
0250 static int test1(struct evsel *evsel, struct machine *machine)
0251 {
0252     int err;
0253     struct hists *hists = evsel__hists(evsel);
0254     /*
0255      * expected output:
0256      *
0257      * Overhead  Command  Shared Object          Symbol
0258      * ========  =======  =============  ==============
0259      *   20.00%     perf  perf           [.] main
0260      *   10.00%     bash  [kernel]       [k] page_fault
0261      *   10.00%     bash  bash           [.] main
0262      *   10.00%     bash  bash           [.] xmalloc
0263      *   10.00%     perf  [kernel]       [k] page_fault
0264      *   10.00%     perf  [kernel]       [k] schedule
0265      *   10.00%     perf  libc           [.] free
0266      *   10.00%     perf  libc           [.] malloc
0267      *   10.00%     perf  perf           [.] cmd_record
0268      */
0269     struct result expected[] = {
0270         { 0, 2000, "perf", "perf",     "main" },
0271         { 0, 1000, "bash", "[kernel]", "page_fault" },
0272         { 0, 1000, "bash", "bash",     "main" },
0273         { 0, 1000, "bash", "bash",     "xmalloc" },
0274         { 0, 1000, "perf", "[kernel]", "page_fault" },
0275         { 0, 1000, "perf", "[kernel]", "schedule" },
0276         { 0, 1000, "perf", "libc",     "free" },
0277         { 0, 1000, "perf", "libc",     "malloc" },
0278         { 0, 1000, "perf", "perf",     "cmd_record" },
0279     };
0280 
0281     symbol_conf.use_callchain = false;
0282     symbol_conf.cumulate_callchain = false;
0283     evsel__reset_sample_bit(evsel, CALLCHAIN);
0284 
0285     setup_sorting(NULL);
0286     callchain_register_param(&callchain_param);
0287 
0288     err = add_hist_entries(hists, machine);
0289     if (err < 0)
0290         goto out;
0291 
0292     err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0);
0293 
0294 out:
0295     del_hist_entries(hists);
0296     reset_output_field();
0297     return err;
0298 }
0299 
0300 /* callchain + NO children */
0301 static int test2(struct evsel *evsel, struct machine *machine)
0302 {
0303     int err;
0304     struct hists *hists = evsel__hists(evsel);
0305     /*
0306      * expected output:
0307      *
0308      * Overhead  Command  Shared Object          Symbol
0309      * ========  =======  =============  ==============
0310      *   20.00%     perf  perf           [.] main
0311      *              |
0312      *              --- main
0313      *
0314      *   10.00%     bash  [kernel]       [k] page_fault
0315      *              |
0316      *              --- page_fault
0317      *                  malloc
0318      *                  main
0319      *
0320      *   10.00%     bash  bash           [.] main
0321      *              |
0322      *              --- main
0323      *
0324      *   10.00%     bash  bash           [.] xmalloc
0325      *              |
0326      *              --- xmalloc
0327      *                  malloc
0328      *                  xmalloc     <--- NOTE: there's a cycle
0329      *                  malloc
0330      *                  xmalloc
0331      *                  main
0332      *
0333      *   10.00%     perf  [kernel]       [k] page_fault
0334      *              |
0335      *              --- page_fault
0336      *                  sys_perf_event_open
0337      *                  run_command
0338      *                  main
0339      *
0340      *   10.00%     perf  [kernel]       [k] schedule
0341      *              |
0342      *              --- schedule
0343      *                  run_command
0344      *                  main
0345      *
0346      *   10.00%     perf  libc           [.] free
0347      *              |
0348      *              --- free
0349      *                  cmd_record
0350      *                  run_command
0351      *                  main
0352      *
0353      *   10.00%     perf  libc           [.] malloc
0354      *              |
0355      *              --- malloc
0356      *                  cmd_record
0357      *                  run_command
0358      *                  main
0359      *
0360      *   10.00%     perf  perf           [.] cmd_record
0361      *              |
0362      *              --- cmd_record
0363      *                  run_command
0364      *                  main
0365      *
0366      */
0367     struct result expected[] = {
0368         { 0, 2000, "perf", "perf",     "main" },
0369         { 0, 1000, "bash", "[kernel]", "page_fault" },
0370         { 0, 1000, "bash", "bash",     "main" },
0371         { 0, 1000, "bash", "bash",     "xmalloc" },
0372         { 0, 1000, "perf", "[kernel]", "page_fault" },
0373         { 0, 1000, "perf", "[kernel]", "schedule" },
0374         { 0, 1000, "perf", "libc",     "free" },
0375         { 0, 1000, "perf", "libc",     "malloc" },
0376         { 0, 1000, "perf", "perf",     "cmd_record" },
0377     };
0378     struct callchain_result expected_callchain[] = {
0379         {
0380             1, {    { "perf",     "main" }, },
0381         },
0382         {
0383             3, {    { "[kernel]", "page_fault" },
0384                 { "libc",     "malloc" },
0385                 { "bash",     "main" }, },
0386         },
0387         {
0388             1, {    { "bash",     "main" }, },
0389         },
0390         {
0391             6, {    { "bash",     "xmalloc" },
0392                 { "libc",     "malloc" },
0393                 { "bash",     "xmalloc" },
0394                 { "libc",     "malloc" },
0395                 { "bash",     "xmalloc" },
0396                 { "bash",     "main" }, },
0397         },
0398         {
0399             4, {    { "[kernel]", "page_fault" },
0400                 { "[kernel]", "sys_perf_event_open" },
0401                 { "perf",     "run_command" },
0402                 { "perf",     "main" }, },
0403         },
0404         {
0405             3, {    { "[kernel]", "schedule" },
0406                 { "perf",     "run_command" },
0407                 { "perf",     "main" }, },
0408         },
0409         {
0410             4, {    { "libc",     "free" },
0411                 { "perf",     "cmd_record" },
0412                 { "perf",     "run_command" },
0413                 { "perf",     "main" }, },
0414         },
0415         {
0416             4, {    { "libc",     "malloc" },
0417                 { "perf",     "cmd_record" },
0418                 { "perf",     "run_command" },
0419                 { "perf",     "main" }, },
0420         },
0421         {
0422             3, {    { "perf",     "cmd_record" },
0423                 { "perf",     "run_command" },
0424                 { "perf",     "main" }, },
0425         },
0426     };
0427 
0428     symbol_conf.use_callchain = true;
0429     symbol_conf.cumulate_callchain = false;
0430     evsel__set_sample_bit(evsel, CALLCHAIN);
0431 
0432     setup_sorting(NULL);
0433     callchain_register_param(&callchain_param);
0434 
0435     err = add_hist_entries(hists, machine);
0436     if (err < 0)
0437         goto out;
0438 
0439     err = do_test(hists, expected, ARRAY_SIZE(expected),
0440               expected_callchain, ARRAY_SIZE(expected_callchain));
0441 
0442 out:
0443     del_hist_entries(hists);
0444     reset_output_field();
0445     return err;
0446 }
0447 
0448 /* NO callchain + children */
0449 static int test3(struct evsel *evsel, struct machine *machine)
0450 {
0451     int err;
0452     struct hists *hists = evsel__hists(evsel);
0453     /*
0454      * expected output:
0455      *
0456      * Children      Self  Command  Shared Object                   Symbol
0457      * ========  ========  =======  =============  =======================
0458      *   70.00%    20.00%     perf  perf           [.] main
0459      *   50.00%     0.00%     perf  perf           [.] run_command
0460      *   30.00%    10.00%     bash  bash           [.] main
0461      *   30.00%    10.00%     perf  perf           [.] cmd_record
0462      *   20.00%     0.00%     bash  libc           [.] malloc
0463      *   10.00%    10.00%     bash  [kernel]       [k] page_fault
0464      *   10.00%    10.00%     bash  bash           [.] xmalloc
0465      *   10.00%    10.00%     perf  [kernel]       [k] page_fault
0466      *   10.00%    10.00%     perf  libc           [.] malloc
0467      *   10.00%    10.00%     perf  [kernel]       [k] schedule
0468      *   10.00%    10.00%     perf  libc           [.] free
0469      *   10.00%     0.00%     perf  [kernel]       [k] sys_perf_event_open
0470      */
0471     struct result expected[] = {
0472         { 7000, 2000, "perf", "perf",     "main" },
0473         { 5000,    0, "perf", "perf",     "run_command" },
0474         { 3000, 1000, "bash", "bash",     "main" },
0475         { 3000, 1000, "perf", "perf",     "cmd_record" },
0476         { 2000,    0, "bash", "libc",     "malloc" },
0477         { 1000, 1000, "bash", "[kernel]", "page_fault" },
0478         { 1000, 1000, "bash", "bash",     "xmalloc" },
0479         { 1000, 1000, "perf", "[kernel]", "page_fault" },
0480         { 1000, 1000, "perf", "[kernel]", "schedule" },
0481         { 1000, 1000, "perf", "libc",     "free" },
0482         { 1000, 1000, "perf", "libc",     "malloc" },
0483         { 1000,    0, "perf", "[kernel]", "sys_perf_event_open" },
0484     };
0485 
0486     symbol_conf.use_callchain = false;
0487     symbol_conf.cumulate_callchain = true;
0488     evsel__reset_sample_bit(evsel, CALLCHAIN);
0489 
0490     setup_sorting(NULL);
0491     callchain_register_param(&callchain_param);
0492 
0493     err = add_hist_entries(hists, machine);
0494     if (err < 0)
0495         goto out;
0496 
0497     err = do_test(hists, expected, ARRAY_SIZE(expected), NULL, 0);
0498 
0499 out:
0500     del_hist_entries(hists);
0501     reset_output_field();
0502     return err;
0503 }
0504 
0505 /* callchain + children */
0506 static int test4(struct evsel *evsel, struct machine *machine)
0507 {
0508     int err;
0509     struct hists *hists = evsel__hists(evsel);
0510     /*
0511      * expected output:
0512      *
0513      * Children      Self  Command  Shared Object                   Symbol
0514      * ========  ========  =======  =============  =======================
0515      *   70.00%    20.00%     perf  perf           [.] main
0516      *              |
0517      *              --- main
0518      *
0519      *   50.00%     0.00%     perf  perf           [.] run_command
0520      *              |
0521      *              --- run_command
0522      *                  main
0523      *
0524      *   30.00%    10.00%     bash  bash           [.] main
0525      *              |
0526      *              --- main
0527      *
0528      *   30.00%    10.00%     perf  perf           [.] cmd_record
0529      *              |
0530      *              --- cmd_record
0531      *                  run_command
0532      *                  main
0533      *
0534      *   20.00%     0.00%     bash  libc           [.] malloc
0535      *              |
0536      *              --- malloc
0537      *                 |
0538      *                 |--50.00%-- xmalloc
0539      *                 |           main
0540      *                  --50.00%-- main
0541      *
0542      *   10.00%    10.00%     bash  [kernel]       [k] page_fault
0543      *              |
0544      *              --- page_fault
0545      *                  malloc
0546      *                  main
0547      *
0548      *   10.00%    10.00%     bash  bash           [.] xmalloc
0549      *              |
0550      *              --- xmalloc
0551      *                  malloc
0552      *                  xmalloc     <--- NOTE: there's a cycle
0553      *                  malloc
0554      *                  xmalloc
0555      *                  main
0556      *
0557      *   10.00%     0.00%     perf  [kernel]       [k] sys_perf_event_open
0558      *              |
0559      *              --- sys_perf_event_open
0560      *                  run_command
0561      *                  main
0562      *
0563      *   10.00%    10.00%     perf  [kernel]       [k] page_fault
0564      *              |
0565      *              --- page_fault
0566      *                  sys_perf_event_open
0567      *                  run_command
0568      *                  main
0569      *
0570      *   10.00%    10.00%     perf  [kernel]       [k] schedule
0571      *              |
0572      *              --- schedule
0573      *                  run_command
0574      *                  main
0575      *
0576      *   10.00%    10.00%     perf  libc           [.] free
0577      *              |
0578      *              --- free
0579      *                  cmd_record
0580      *                  run_command
0581      *                  main
0582      *
0583      *   10.00%    10.00%     perf  libc           [.] malloc
0584      *              |
0585      *              --- malloc
0586      *                  cmd_record
0587      *                  run_command
0588      *                  main
0589      *
0590      */
0591     struct result expected[] = {
0592         { 7000, 2000, "perf", "perf",     "main" },
0593         { 5000,    0, "perf", "perf",     "run_command" },
0594         { 3000, 1000, "bash", "bash",     "main" },
0595         { 3000, 1000, "perf", "perf",     "cmd_record" },
0596         { 2000,    0, "bash", "libc",     "malloc" },
0597         { 1000, 1000, "bash", "[kernel]", "page_fault" },
0598         { 1000, 1000, "bash", "bash",     "xmalloc" },
0599         { 1000,    0, "perf", "[kernel]", "sys_perf_event_open" },
0600         { 1000, 1000, "perf", "[kernel]", "page_fault" },
0601         { 1000, 1000, "perf", "[kernel]", "schedule" },
0602         { 1000, 1000, "perf", "libc",     "free" },
0603         { 1000, 1000, "perf", "libc",     "malloc" },
0604     };
0605     struct callchain_result expected_callchain[] = {
0606         {
0607             1, {    { "perf",     "main" }, },
0608         },
0609         {
0610             2, {    { "perf",     "run_command" },
0611                 { "perf",     "main" }, },
0612         },
0613         {
0614             1, {    { "bash",     "main" }, },
0615         },
0616         {
0617             3, {    { "perf",     "cmd_record" },
0618                 { "perf",     "run_command" },
0619                 { "perf",     "main" }, },
0620         },
0621         {
0622             4, {    { "libc",     "malloc" },
0623                 { "bash",     "xmalloc" },
0624                 { "bash",     "main" },
0625                 { "bash",     "main" }, },
0626         },
0627         {
0628             3, {    { "[kernel]", "page_fault" },
0629                 { "libc",     "malloc" },
0630                 { "bash",     "main" }, },
0631         },
0632         {
0633             6, {    { "bash",     "xmalloc" },
0634                 { "libc",     "malloc" },
0635                 { "bash",     "xmalloc" },
0636                 { "libc",     "malloc" },
0637                 { "bash",     "xmalloc" },
0638                 { "bash",     "main" }, },
0639         },
0640         {
0641             3, {    { "[kernel]", "sys_perf_event_open" },
0642                 { "perf",     "run_command" },
0643                 { "perf",     "main" }, },
0644         },
0645         {
0646             4, {    { "[kernel]", "page_fault" },
0647                 { "[kernel]", "sys_perf_event_open" },
0648                 { "perf",     "run_command" },
0649                 { "perf",     "main" }, },
0650         },
0651         {
0652             3, {    { "[kernel]", "schedule" },
0653                 { "perf",     "run_command" },
0654                 { "perf",     "main" }, },
0655         },
0656         {
0657             4, {    { "libc",     "free" },
0658                 { "perf",     "cmd_record" },
0659                 { "perf",     "run_command" },
0660                 { "perf",     "main" }, },
0661         },
0662         {
0663             4, {    { "libc",     "malloc" },
0664                 { "perf",     "cmd_record" },
0665                 { "perf",     "run_command" },
0666                 { "perf",     "main" }, },
0667         },
0668     };
0669 
0670     symbol_conf.use_callchain = true;
0671     symbol_conf.cumulate_callchain = true;
0672     evsel__set_sample_bit(evsel, CALLCHAIN);
0673 
0674     setup_sorting(NULL);
0675 
0676     callchain_param = callchain_param_default;
0677     callchain_register_param(&callchain_param);
0678 
0679     err = add_hist_entries(hists, machine);
0680     if (err < 0)
0681         goto out;
0682 
0683     err = do_test(hists, expected, ARRAY_SIZE(expected),
0684               expected_callchain, ARRAY_SIZE(expected_callchain));
0685 
0686 out:
0687     del_hist_entries(hists);
0688     reset_output_field();
0689     return err;
0690 }
0691 
0692 static int test__hists_cumulate(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
0693 {
0694     int err = TEST_FAIL;
0695     struct machines machines;
0696     struct machine *machine;
0697     struct evsel *evsel;
0698     struct evlist *evlist = evlist__new();
0699     size_t i;
0700     test_fn_t testcases[] = {
0701         test1,
0702         test2,
0703         test3,
0704         test4,
0705     };
0706 
0707     TEST_ASSERT_VAL("No memory", evlist);
0708 
0709     err = parse_event(evlist, "cpu-clock");
0710     if (err)
0711         goto out;
0712     err = TEST_FAIL;
0713 
0714     machines__init(&machines);
0715 
0716     /* setup threads/dso/map/symbols also */
0717     machine = setup_fake_machine(&machines);
0718     if (!machine)
0719         goto out;
0720 
0721     if (verbose > 1)
0722         machine__fprintf(machine, stderr);
0723 
0724     evsel = evlist__first(evlist);
0725 
0726     for (i = 0; i < ARRAY_SIZE(testcases); i++) {
0727         err = testcases[i](evsel, machine);
0728         if (err < 0)
0729             break;
0730     }
0731 
0732 out:
0733     /* tear down everything */
0734     evlist__delete(evlist);
0735     machines__exit(&machines);
0736 
0737     return err;
0738 }
0739 
0740 DEFINE_SUITE("Cumulate child hist entries", hists_cumulate);