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